Skip to main content

Customer hold status changed

Fires when a customer's hold status - CustTable.Blocked, the Invoicing and delivery on hold field - changes to a different value during a CustTable update, for example when a customer is placed on hold for all transactions, blocked for invoicing only, or released from hold. It is the same field the vendor twin Vendor hold status changed reports; it is not a credit management hold. The payload carries the customer identity, the new and the previous hold status (each as an integer and a symbol name), and the customer's credit limit, so downstream order-management, e-commerce and credit-control systems can react in near real time.

Event classMGCLatticeCustomerHoldStatusChangedBusinessEvent
Contract classMGCLatticeCustomerHoldStatusChangedBusinessEventContract
CategoryAccounts receivable
ModuleModuleAxapta::Customer
Label IDsCustomerCreditHoldChangedBusinessEventName / CustomerCreditHoldChangedBusinessEventDescription
TriggerCustTable.update() -> orig().Blocked != this.Blocked

Trigger / Hook​

  • Extension class MGCLatticeCustTable_Table_Extension, [ExtensionOf(tableStr(CustTable))].
  • CoC method signature: void update(boolean _updateSmmBusRelTable, boolean _updateParty).
  • Firing condition: when the event is activated (checked first, a cached lookup), the method captures this.orig().Blocked before calling next update(...), then compares it against this.Blocked after the update. The event is sent only when origBlocked != this.Blocked - any change between two values counts (for example Invoice to All, not only on/off hold). The same update() method independently sends MGCLatticeCustomerUpdatedBusinessEvent on every update, so a Blocked change raises both events, the Customer updated event first.
  • Not covered: a customer that is created already blocked (inserts do not raise this event), and writes that bypass CustTable.update() (doUpdate(), or set-based updates run with skipDataMethods(true)).
  • Timing: send() runs immediately after the update and writes the event to the business events commit log within whatever transaction the caller has open; if that transaction is rolled back, the event is rolled back with it and never delivered. Delivery happens asynchronously after commit.
  • Enablement gate: BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeCustomerHoldStatusChangedBusinessEvent)) must return true (the event is activated for the current legal entity); when it is not, the original buffer is not read at all.
void update(boolean _updateSmmBusRelTable, boolean _updateParty)
{
// The activation check is a cached lookup; read the original buffer only when the event is on.
boolean holdEventEnabled = BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeCustomerHoldStatusChangedBusinessEvent));
CustVendorBlocked origBlocked = holdEventEnabled ? this.orig().Blocked : this.Blocked;

next update(_updateSmmBusRelTable, _updateParty);

if (BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeCustomerUpdatedBusinessEvent)))
{
MGCLatticeCustomerUpdatedBusinessEvent::newFromCustTable(this).send();
}

if (holdEventEnabled && origBlocked != this.Blocked)
{
MGCLatticeCustomerHoldStatusChangedBusinessEvent::newFromCustTable(this, origBlocked).send();
}
}

Payload Contract​

One row per [DataMember], in declaration order. All sources are read from the updated CustTable record in initialize().

JSON fieldDisplay labelType / EDTSourceNotes
legalEntityLegal EntityDataAreaIdCustTable.DataAreaIdCompany / data area of the customer record, in lower case (for example usmf).
customerAccountCustomer AccountCustAccountCustTable.AccountNumCustomer account number.
customerNameCustomer NamestrCustTable.name()Resolved via the name() display method (DirParty name lookup).
blockedStatusBlocked Statusintenum2int(CustTable.Blocked)The new value of the CustVendorBlocked enum as an integer: 0 = No, 1 = Invoice, 2 = All, 3 = Payment, 4 = Requisition, 5 = Never, 6 = PurchOrder.
blockedStatusNameBlocked Status Namestrenum2Symbol(enumNum(CustVendorBlocked), enum2int(CustTable.Blocked))Symbol of the new value (for example No, Invoice, All, Never).
previousBlockedStatusPrevious Blocked Statusintenum2int(CustTable.orig().Blocked)The value before the update, same integers as blockedStatus.
previousBlockedStatusNamePrevious Blocked Status Namestrenum2Symbol(enumNum(CustVendorBlocked), ...)Symbol of the value before the update.
creditLimitMSTCredit Limit MSTAmountMSTCustTable.CreditMaxCustomer credit limit, in the legal entity's accounting currency (CreditMax is EDT CustCreditMaxMST).
crossReferencesCross referencesList of MGCLatticeCrossReferenceEventContractMGCLatticeCrossReferenceEventHelper::listFor(CustTable)Keys external systems hold for the customer: one { externalSystem, externalKey } object per external system, ordered by external system, historical keys included; [] when it has none. See Cross-reference keys.

Every Lattice event also carries the Lattice ordering and correlation envelope, inherited from MGCLatticeBusinessEventContractBase: eventSequence (Int64 - increasing across the whole catalog and all companies, allocated when the event is raised inside the business transaction, not when it commits; it orders the events of one business record, gaps are permanent and normal, and it must not be used to re-sequence the whole stream), correlationId (String, always Scope:Key - groups emissions that belong to one logical run; an event that joins no run carries Event: followed by a lower-case GUID unique to this emission) and schemaVersion (Int - the payload shape version; 1 for this contract). D365 F&O also adds its standard envelope fields to every business event payload: BusinessEventId, BusinessEventLegalEntity, ContextRecordSubject, ControlNumber, EventId, EventTime, EventTimeIso8601, InitiatingUserAADObjectId, MajorVersion, MinorVersion, and ParentContextRecordSubjects. Do not rely on the order of members in the delivered JSON.

Example Payload​

{
"BusinessEventId": "MGCLatticeCustomerHoldStatusChangedBusinessEvent",
"ControlNumber": 5637148502,
"EventId": "1F2A4C6E-8B0D-42F1-9A3C-7E5D1B9F0C44",
"EventTime": "\/Date(1790247806000)\/",
"EventTimeIso8601": "2026-09-24T11:03:26.6507400Z",
"MajorVersion": 0,
"MinorVersion": 0,
"BusinessEventLegalEntity": "USMF",
"ContextRecordSubject": "",
"InitiatingUserAADObjectId": "{9BC563FE-C60E-E236-CEC3-7D55FC1F98F1}",
"ParentContextRecordSubjects": [],
"eventSequence": 48228,
"correlationId": "Event:d41f8a06-3e27-4b9c-a5d8-6c1e2f90b347",
"schemaVersion": 1,
"legalEntity": "usmf",
"customerAccount": "US-027",
"customerName": "Cave Wholesale Bikes",
"blockedStatus": 2,
"blockedStatusName": "All",
"previousBlockedStatus": 0,
"previousBlockedStatusName": "No",
"creditLimitMST": 50000.00,
"crossReferences": [
{
"externalSystem": "CRM",
"externalKey": "ACC-000481"
}
]
}

Activation​

In the D365FO client, go to System administration > Setup > Business events > Business events catalog. Find the event by its name ("Customer hold status changed") or by filtering the Category column to Accounts receivable. Select it and use Activate to bind it to a configured endpoint (for example, an Azure Service Bus queue, Event Grid topic, or HTTPS webhook).