Skip to main content

Fixed asset disposal posted

Fires when a fixed asset disposal transaction is written to the asset ledger, either a disposal by sale or a disposal by scrap, and also for the rows a transaction reversal or an asset reclassification writes with those transaction types, which the payload flags with isReversal and isReclassification. The event captures the asset, its book, the amount in the company currency, the voucher and the transaction date so downstream systems can record the retirement of the asset and reconcile gain/loss on disposal.

Event classMGCLatticeFixedAssetDisposalPostedBusinessEvent
Contract classMGCLatticeFixedAssetDisposalPostedBusinessEventContract
CategoryFixed assets
ModuleModuleAxapta::FixedAssets
Label IDsFixedAssetDisposalPostedBusinessEventName / FixedAssetDisposalPostedBusinessEventDescription
TriggerAssetTrans.insert() -> TransType == DisposalSale or DisposalScrap

Trigger / Hook​

  • Extension class: MGCLatticeAssetTrans_Table_Extension, [ExtensionOf(tableStr(AssetTrans))]
  • CoC method signature: void insert()
  • Firing condition: after next insert(), the new AssetTrans record's TransType is checked. The disposal event is sent only when TransType == AssetTransType::DisposalSale || TransType == AssetTransType::DisposalScrap. (An Acquisition transaction in the same method sends the sibling acquisition event instead.)
  • One event per AssetTrans row of those types: a disposal posted to several books, including derived books, raises one event per book. Disposal by sale can be posted from a fixed assets journal or from a customer invoice line for the asset; both write a DisposalSale row.
  • The disposal posting also writes summary rows that reverse the asset's acquisition, depreciation and other values and record the net book value and profit or loss. Those rows use other transaction types (for example AcqThisYear, DepPriorYears, NetBookValue, ProfitLoss) and do not raise this event.
  • Who writes disposal rows: asset posting, the transaction reversal function, and asset reclassification. All of them raise the event:
    • Posting - isReversal and isReclassification are both false.
    • Reversal - the Reverse transaction function writes a copy of the original row with the amount negated; revoking a reversal writes another copy with the original sign. Both rows have isReversal = true. They are marked by MGCLatticeTransactionReversal_Asset_Class_Extension, which wraps TransactionReversal_Asset.createAssetTrans() in an MGCLatticeAssetTransOriginContext reversal scope; nothing on the row itself identifies a reversal when it is inserted.
    • Reclassification - asset reclassification copies every transaction of a book that is still open to the new asset and writes a negated copy on the old asset, so a disposal row on such a book raises the event twice, with isReclassification = true (from the reclassification scope that MGCLatticeAssetReclassification_Class_Extension opens around AssetReclassification.run(), and, in Germany and Austria, from D365's own AssetTrans.Reclassification flag).
  • Inserts that bypass the table's insert() method (doInsert(), or set-based inserts with data methods skipped) do not raise it.
  • Timing: AssetTrans rows are written inside the posting, reversal or reclassification transaction. send() writes the event to the business events commit log in that transaction and it is delivered after commit, so a posting that rolls back never delivers the event.
  • Enablement gate: BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeFixedAssetDisposalPostedBusinessEvent)) must return true before the event is sent.
void insert()
{
next insert();

boolean isAcquisition = this.TransType == AssetTransType::Acquisition;
boolean isDisposal = this.TransType == AssetTransType::DisposalSale || this.TransType == AssetTransType::DisposalScrap;

if (!isAcquisition && !isDisposal)
{
return;
}

// Read the writer's scope now: the reversal link that would identify a reversing row is written after it.
boolean isReversal = MGCLatticeAssetTransOriginContext::isReversalInProgress();
boolean isReclassification = MGCLatticeAssetTransOriginContext::isReclassificationInProgress();

if (isAcquisition)
{
if (BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeFixedAssetAcquisitionPostedBusinessEvent)))
{
MGCLatticeFixedAssetAcquisitionPostedBusinessEvent::newFromAssetTrans(this, isReversal, isReclassification).send();
}
}
else
{
if (BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeFixedAssetDisposalPostedBusinessEvent)))
{
MGCLatticeFixedAssetDisposalPostedBusinessEvent::newFromAssetTrans(this, isReversal, isReclassification).send();
}
}
}

Payload Contract​

Fields in declaration order, populated by MGCLatticeFixedAssetDisposalPostedBusinessEventContract::initialize(AssetTrans _assetTrans, boolean _isReversal, boolean _isReclassification):

JSON fieldDisplay labelType / EDTSourceNotes
legalEntityLegal EntityDataAreaId_assetTrans.DataAreaIdCompany ID the disposal was posted in, in lower case (for example usmf)
assetIdAsset IDAssetId_assetTrans.AssetIdFixed asset being disposed; for a reclassification, the old or the new asset
bookIdBook IDAssetBookId_assetTrans.BookIdBook the transaction posted to
disposalAmountMSTDisposal Amount MSTAmountMST_assetTrans.AmountMSTAmount of the sale or scrap row in the accounting (company) currency, signed as on the asset transaction. A sale posts the sale proceeds as a negative amount; a reversal carries the opposite sign
transDateTransaction DateTransDate_assetTrans.TransDateDate of the asset transaction (the reversal or reclassification date for those rows); "\/Date(ms)\/" form
voucherVoucherVoucher_assetTrans.VoucherVoucher of the asset transaction; a reversal and a reclassification each have their own voucher
isReversalIs ReversalbooleanReversal scope when the row was insertedtrue when the transaction reversal function wrote the row (a reversal, or the revoke of one); written as true/false
isReclassificationIs ReclassificationbooleanReclassification scope, or _assetTrans.Reclassificationtrue when the row belongs to an asset reclassification; written as true/false
crossReferencesCross referencesList of MGCLatticeCrossReferenceEventContractMGCLatticeCrossReferenceEventHelper::listForFixedAsset(AssetTrans.AssetId, AssetTrans.DataAreaId)Keys external systems hold for the fixed asset: 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.

This event does not join a run: correlationId is unique to each emission (rows for several books do not share it).

Example Payload​

{
"BusinessEventId": "MGCLatticeFixedAssetDisposalPostedBusinessEvent",
"ControlNumber": 587213,
"EventId": "B0D2F4C1-9E3A-4D7B-A6C2-1F8E5A9C3B47",
"EventTime": "\/Date(1790265909000)\/",
"EventTimeIso8601": "2026-09-24T16:05:09.6544460Z",
"MajorVersion": 0,
"MinorVersion": 0,
"BusinessEventLegalEntity": "USMF",
"ContextRecordSubject": "",
"InitiatingUserAADObjectId": "{AA096874-424B-0B47-EC96-B70A962844A7}",
"ParentContextRecordSubjects": [],
"eventSequence": 48655,
"correlationId": "Event:81c6e0a3-d95f-4b2e-a437-6e0b2f8d1c94",
"schemaVersion": 1,
"legalEntity": "usmf",
"assetId": "COMP-000071",
"bookId": "200_SLLR",
"disposalAmountMST": -5000.00,
"transDate": "\/Date(1790208000000)\/",
"voucher": "FADS000042",
"isReversal": false,
"isReclassification": false,
"crossReferences": [
{
"externalSystem": "LEGACYERP",
"externalKey": "FA-7731"
}
]
}

Reversing that disposal raises the event again for the same asset and book with "disposalAmountMST": 5000.00, the reversal's own voucher and date, and "isReversal": true.

Activation​

In the D365FO client, go to System administration > Setup > Business events > Business events catalog. Find the event by name ("Fixed asset disposal posted") or by filtering the Category column to Fixed assets. Select the event and use Activate to bind it to an endpoint (for example an Azure Service Bus queue, Event Grid topic, or Power Automate Flow).