Skip to main content

Collection letter posted

Fires when a collection letter is posted for a customer with Post collection letters - once per letter that posting actually posts. It carries the customer, the collection letter number and level, the letter date, due date, fee and currency, the posting date and, when the letter charges a fee, the fee voucher, so credit teams can drive external follow-up such as sending the letter through another channel or scheduling a call. Creating collection letters does not raise it; only posting does.

Event classMGCLatticeCollectionLetterPostedBusinessEvent
Contract classMGCLatticeCollectionLetterPostedBusinessEventContract
CategoryAccounts receivable
ModuleModuleAxapta::Customer
Label IDsCollectionLetterPostedBusinessEventName / CollectionLetterPostedBusinessEventDescription
TriggerCustCollectionLetterPost.writeCustCollectionLetterJour() -> the letter being written has status Posted

Trigger / Hook​

  • Extension class: MGCLatticeCustCollectionLetterPost_Class_Extension, [ExtensionOf(classStr(CustCollectionLetterPost))], wrapping protected void writeCustCollectionLetterJour(CustCollectionLetterJour _custCollectionLetterJour) with Chain of Command. The event is sent by MGCLatticeCollectionsEventHandlers::raiseCollectionLetterPosted().
  • When it runs: Post collection letters (CustCollectionLetterPost) processes each selected letter in processRow(). For a letter that passes validation it posts the fee (when the letter has one), sets the status to Posted with the posting date, applies the customer block if the letter is set to block, and then calls writeCustCollectionLetterJour() to save the letter - which is when the event is sent. A letter that fails validation (for example one that is already posted or canceled) is not written and raises nothing. Batch posting splits the letters into subset tasks that run the same code.
  • Firing condition: the written letter exists and its status is Posted.
  • Creating letters: Create collection letters (CustCollectionLetterCreate, also run by the Collections process automation) does not raise this event. A letter that is created and later canceled, or replaced before it is posted, is never announced.
  • Timing: posting runs in one transaction (CustCollectionLetterPost.run()); send() writes to the business events commit log inside it and delivery happens asynchronously after commit, so a posting run that is rolled back never delivers.
  • Enablement gate: BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeCollectionLetterPostedBusinessEvent)).
protected void writeCustCollectionLetterJour(CustCollectionLetterJour _custCollectionLetterJour)
{
next writeCustCollectionLetterJour(_custCollectionLetterJour);

MGCLatticeCollectionsEventHandlers::raiseCollectionLetterPosted(_custCollectionLetterJour);
}

raiseCollectionLetterPosted() sends the event when the letter has a record ID and status Posted and the event is activated.

Payload Contract​

One row per [DataMember], in declaration order. All sources are fields on the posted CustCollectionLetterJour record, mapped in initialize().

JSON fieldDisplay labelType / EDTSourceNotes
legalEntityLegal EntityDataAreaIdCustCollectionLetterJour.DataAreaIdCompany of the letter, in lower case (for example usmf).
customerAccountCustomer AccountCustAccountCustCollectionLetterJour.AccountNumCustomer the letter is for.
customerNameCustomer NameNameCustCollectionLetterJour.NameCustomer name stored on the collection letter journal.
collectionLetterNumCollection Letter NumberCollectionLetterNumCustCollectionLetterJour.CollectionLetterNumLetter number; the Dunning level changed events for the letter's transactions carry the same number.
collectionLetterCodeDunning Levelintenum2int(CustCollectionLetterJour.CollectionLetterCode)CustCollectionLetterCode: 0 = None, 1 = CollectionLetter1, 2 = CollectionLetter2, 3 = CollectionLetter3, 4 = CollectionLetter4, 5 = Collection, 6 = All, 7 = CollectionPerCust.
collectionLetterCodeNameDunning Level Namestrenum2Symbol(enumNum(CustCollectionLetterCode), ...)Symbol of the level, for example CollectionLetter2.
collectionLetterDateCollection Letter DateTransDateCustCollectionLetterJour.CollectionLetterDateLetter date (date, \/Date(milliseconds)\/ form).
dueDateDue DateDueDateCustCollectionLetterJour.DueDatePayment due date on the letter, calculated from the collection letter sequence's terms of payment or, if it has none, the customer's.
feeFeeAmountCurCustCollectionLetterJour.FeeCollection letter fee, in currencyCode.
currencyCodeCurrency CodeCurrencyCodeCustCollectionLetterJour.CurrencyCodeCurrency of the letter.
voucherVoucherVoucherCustCollectionLetterJour.LedgerVoucherVoucher of the fee posting. Empty when the letter has no fee (posting creates no voucher then).
postingDatePosting DateTransDateCustCollectionLetterJour.UpdatedDate the letter was posted (the posting date chosen in Post collection letters, or the run date when it is set to use it).
statusStatusintenum2int(CustCollectionLetterJour.Status)PrintPostCancel: 0 = Created, 2 = Posted, 3 = Canceled. Always 2 in this event.
statusNameStatus Namestrenum2Symbol(enumNum(PrintPostCancel), ...)Always Posted in this event.

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": "MGCLatticeCollectionLetterPostedBusinessEvent",
"ControlNumber": 5637148802,
"EventId": "6C2F8A13-D540-4B97-A3E6-0F9B7D1C5E82",
"EventTime": "\/Date(1790338173000)\/",
"EventTimeIso8601": "2026-09-25T12:09:33.3723462Z",
"MajorVersion": 0,
"MinorVersion": 0,
"BusinessEventLegalEntity": "USMF",
"ContextRecordSubject": "",
"InitiatingUserAADObjectId": "{FF261267-C338-FE16-BA86-5ED3F3CF534C}",
"ParentContextRecordSubjects": [],
"eventSequence": 48433,
"correlationId": "Event:28e5b7c0-9d1a-4f63-b4e8-7a0c3f2d6b19",
"schemaVersion": 1,
"legalEntity": "usmf",
"customerAccount": "US-007",
"customerName": "Desert Wholesales",
"collectionLetterNum": "000023",
"collectionLetterCode": 2,
"collectionLetterCodeName": "CollectionLetter2",
"collectionLetterDate": "\/Date(1790294400000)\/",
"dueDate": "\/Date(1792022400000)\/",
"fee": 25.00,
"currencyCode": "USD",
"voucher": "CLV-000041",
"postingDate": "\/Date(1790294400000)\/",
"status": 2,
"statusName": "Posted"
}

Activation​

In the D365FO client, go to System administration > Setup > Business events > Business events catalog. Find this event by name ("Collection letter posted") 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).

  • Dunning level changed - one event per customer transaction on the letter whose collection letter level changes; with the default setting the levels change when the letter is posted, right after this event.
  • Collection case changed - collections cases opened or closed for the customer.
  • Customer hold status changed - posting a collection letter that is set to block the customer changes an unblocked customer's Blocked status to Invoice, which raises that event.