版本19.104:销售订单添加套件项仅最后一行生效求助
解决Acumatica 19.104中销售订单多行套件免费项仅最后一行生效的问题
嘿,我看了你遇到的这个问题——循环生成销售订单行时,只有最后一行的套件免费项能成功添加到订单里,前面行的套件项都没了。这个问题根源在于你在每次添加行后都立刻调用了PressSave(),频繁保存会重置Acumatica Graph的缓存状态,破坏了循环里的上下文关联,最后只有最后一次循环的内容被保留下来。
问题出在哪?
你的代码在每添加一个主订单行、每添加一个套件行后都调用orderEntry.Actions.PressSave(),这会导致:
- 每次Save都会把当前缓存里的数据提交到数据库,然后重置Graph的缓存
- 后续循环添加的行没法正确关联到之前创建的订单,之前加的套件行要么被覆盖,要么丢失了关联关系
修复后的代码
我给你调整了代码逻辑,把所有行都先加到缓存里,最后统一保存,这样就能保证所有行都能正确关联到订单:
public PXSelect<INKitSpecStkDet, Where<INKitSpecStkDet.kitInventoryID, Equal<Required<INKitSpecStkDet.kitInventoryID>>, And<INKitSpecStkDet.revisionID, Equal<Required<INKitSpecStkDet.revisionID>>>>> KitStockItems; .... public PXAction<MyOrder> MyAction; [PXButton(CommitChanges = true)] [PXUIField(DisplayName = "My Action")] protected void myAction() { SOOrderEntry orderEntry = PXGraph.CreateInstance<SOOrderEntry>(); using (PXTransactionScope transScope = new PXTransactionScope()) { orderEntry.Clear(); SOOrder newOrder = new SOOrder(); newOrder.OrderType = PX.Objects.SO.SOOrderTypeConstants.SalesOrder; newOrder = orderEntry.CurrentDocument.Insert(newOrder); newOrder.CustomerID = CurrentDocument.Current.CustomerID; newOrder.OrderDesc = CurrentDocument.Current.OrderDesc; newOrder.OrderDate = this.Accessinfo.BusinessDate; newOrder.ProjectID = CurrentDocument.Current.ProjectID; newOrder.BranchID = CurrentDocument.Current.BranchID; newOrder.Hold = true; newOrder.Status = PX.Objects.SO.SOOrderStatus.Hold; newOrder = orderEntry.CurrentDocument.Update(newOrder); // 先不保存订单,先把所有行都加进缓存 foreach (OrderLine line in Transactions.Select()) { SOLine newLine = orderEntry.Transactions.Insert(); newLine.LineType = PX.Objects.SO.SOLineType.Inventory; newLine.Operation = PX.Objects.SO.SOOperation.Issue; newLine.OrderType = newOrder.OrderType; newLine.InventoryID = line.InventoryID; newLine.BranchID = newOrder.BranchID; newLine.Qty = line.OrderQty; newLine.CuryUnitPrice = line.CuryUnitPrice; newLine.CuryExtPrice = line.CuryUnitPrice * line.OrderQty; // 这里修正了总价计算,之前直接用了单价,应该是单价×数量 newLine.UOM = line.Uom; newLine.SiteID = line.Siteid; newLine = orderEntry.Transactions.Update(newLine); // 不在这里保存主行 // 添加套件免费项 PXResultset<INKitSpecStkDet> resultSet = KitStockItems.Select(new object[] { line.InventoryID, line.KitRevisionID }); foreach (PXResult stkItem in resultSet) { INKitSpecStkDet kitItem = stkItem.GetItem<INKitSpecStkDet>(); SOLine stkKitLine = orderEntry.Transactions.Insert(); stkKitLine.InventoryID = kitItem.CompInventoryID; stkKitLine.Qty = kitItem.DfltCompQty * line.OrderQty; stkKitLine.UOM = kitItem.UOM; stkKitLine.IsFree = true; stkKitLine.LineType = PX.Objects.SOLineType.Inventory; // 明确设置行类型,避免默认值出问题 stkKitLine.Operation = PX.Objects.SO.SOOperation.Issue; stkKitLine.OrderType = newOrder.OrderType; stkKitLine.BranchID = newOrder.BranchID; stkKitLine.SiteID = line.Siteid; // 继承主行的仓库ID stkKitLine = orderEntry.Transactions.Update(stkKitLine); // 也不在这里保存套件行 } } // 所有行都加完了,统一保存订单 orderEntry.Actions.PressSave(); transScope.Complete(); } this.Actions.PressSave(); }
关键修改说明
- 移除循环内的
PressSave():只在所有订单行和套件行都添加到缓存后执行一次保存,这样Graph的状态始终一致,所有行都能正确关联到目标订单。 - 修正总价计算:原代码里
CuryExtPrice直接用了单价,改成了单价×数量,避免财务数据错误。 - 补全套件行的必要字段:给套件行明确设置
LineType、Operation等字段,防止因为默认值缺失导致的关联问题。 - 统一事务处理:所有操作都在
PXTransactionScope里完成,确保要么全成功要么全回滚,不会出现半拉子数据。
额外小建议
- 在Acumatica里操作Graph时,尽量少调用
PressSave(),频繁保存不仅容易出问题,还会降低性能。 - 调试的时候,可以用
orderEntry.Transactions.View.Cache查看缓存里的所有行,确认是不是都加进去了。
内容的提问来源于stack exchange,提问作者MikeNIke
相关产品推荐
相关产品推荐

