Sharing this fix with the community. This is a very unusual bug that happened randomly.
Symptom:
Editing one of these three columns in the PO line screen.
Threw this error..."Cannot create a record in Relationship between the purchase order line and the inventory transactions originator (InventTransOriginPurchLine). Inventory transactions originator: XXX, XXX. The record already exists"
Cause:
Native AX code relies on an exception to determine when to "insert" or "update" record. Relying on an exception is not a good practice.
Resolution:
I overhauled the problematic method InventTransOriginPurchLine->writeOriginOwnerRelationship().
Below has more info.
Copy/paste the code below into table method InventTransOriginPurchLine->writeOriginOwnerRelationship(). Side note...I tried pasting this code into a "code bloc" but the forum mangled the post.
/// ★★★★★★★★★★★★
/// 2021-06-28 Overhauled method.
/// Bug happened randomly when updating fields Price, Qty, Delivery Date. AX would throw error message "Cannot create a record in Relationship between the purchase order line and the inventory transactions originator (InventTransOriginPurchLine). Inventory transactions originator: XXX, XXX. The record already exists" -RR
/// The native method was poorly written. Native method relied on the insert command failing (then throwing an exception) to determine if need to "update" instead.
/// The whole method is overhauled.
/// ★★★★★★★★★★★★
public static server void writeOriginOwnerRelationship(
DataAreaId _purchLineDataAreaId,
InventTransId _purchLineInventTransId,
InventTransOriginId _inventTransOriginId)
{
InventTransOriginPurchLine inventTransOriginPurchLine;
Counter logCount = infologLine();
//Used to count records. -RR
InventTransOriginPurchLine inventTransOriginPurchLine_TempRR;
//Original method relied on the insert command throwing an exception to know if needed to update (bad code).
//New method below checks if record exists. So no need for exception handling. -RR
select count(RecId)
from inventTransOriginPurchLine_TempRR
where
1==1
&& inventTransOriginPurchLine_TempRR.PurchLineDataAreaId == _purchLineDataAreaId
&& inventTransOriginPurchLine_TempRR.PurchLineInventTransId == _purchLineInventTransId
&& inventTransOriginPurchLine_TempRR.InventTransOrigin == _inventTransOriginId
;
//Debug: Lines counted
//info(int2str(inventTransOriginPurchLine_TempRR.RecId));
ttsBegin;
//No records exist, so insert.
//In this context, property RecId = record count. -RR
if (inventTransOriginPurchLine_TempRR.RecId == 0)
{
inventTransOriginPurchLine.PurchLineDataAreaId = _purchLineDataAreaId;
inventTransOriginPurchLine.PurchLineInventTransId = _purchLineInventTransId;
inventTransOriginPurchLine.InventTransOrigin = _inventTransOriginId;
inventTransOriginPurchLine.insert();
//Debug:
//info("inserted");
}
//Record exists, so update.
else
{
//Side note...I don't see the point of this code block. The updates I have tested did not change the InventTransOriginId column value.
//Also, once the InventTransOrigin record is created, I believe it is meant to last for life.
//Anyhow, will leave it in for the heck of it. -RR
update_recordset inventTransOriginPurchLine
setting InventTransOrigin = _inventTransOriginId
where inventTransOriginPurchLine.PurchLineInventTransId == _purchLineInventTransId
&& inventTransOriginPurchLine.PurchLineDataAreaId == _purchLineDataAreaId
&& inventTransOriginPurchLine.InventTransOrigin != _inventTransOriginId
;
//Debug:
//info("updated");
}
ttsCommit;
}
Usual disclaimer...Use above at your own risk.