Acumatica - 修订版
Acumatica - Revision
我们有 2 个 DAC - Master 和 Child
主DAC
#region MasterID
public abstract class masterID:PX.Data.BQL.BqlInt.Field<masterID> { }
protected int? _MasterID;
[PXDBIdentity()]
[PXUIField(Visibility = PXUIVisibility.Invisible)]
[PXReferentialIntegrityCheck]
public virtual int? MasterID
{
get {return this._MasterID;}
set {this._MasterID = value;}
}
#endregion
#region MasterCD
public abstract class masterRoutingCD:PX.Data.BQL.BqlString.Field<masterCD> { }
protected string _MasterRoutingCD;
[BomID(DisplayName = "Master #", IsKey = true, Required = true,
Visibility = PXUIVisibility.SelectorVisible)]
[PXDefault]
[Rev.Key(typeof(Setup.pMMasterNumberSequenceID),
typeof(Master.masterCD),
typeof(Master.revisionNo),
typeof(Master.masterCD),
typeof(Master.revisionNo)
)]
public virtual string MasterCD
{
get {return this._MasterCD;}
set {this._MasterCD = value;}
}
#endregion
#region RevisionNo
public abstract class revisionNo:PX.Data.IBqlField { }
protected string _RevisionNo;
[RevisionIDField(IsKey = true, Visibility = PXUIVisibility.SelectorVisible,
Required = true)]
[PXDefault(typeof(Master.defaultRevisionNo),
PersistingCheck = PXPersistingCheck.Nothing)]
[Rev.ID(typeof(Master.defaultRevisionNo),
typeof(Master.masterCD),
typeof(Master.revisionNo),
typeof(Master.revisionNo),
typeof(Master.description),
typeof(Master.fromDate),
typeof(Master.toDate))]
public virtual string RevisionNo
{
get {return this._RevisionNo;}
set {this._RevisionNo = value;}
}
#endregion
子DAC
public abstract class childID:PX.Data.BQL.BqlInt.Field<childID> { }
protected int? _ChildID;
[PXDBIdentity()]
//[PXReferentialIntegrityCheck]
public virtual int? ChildID
{
get {return this._ChildID;}
set {this._ChildID = value;}
}
#endregion
#region MasterID
public abstract class masterID:PX.Data.BQL.BqlInt.Field<masterID> { }
protected int? _MasterID;
[PXDBInt()]
[PXDBDefault(typeof(Master.masterID))]
[PXParent(typeof(Select<Master, Where<Master.masterRoutingCD, Equal<Current<masterCD>>,
And<Master.revisionNo, Equal<Current<revisionNo>>>>>))]
public virtual int? MasterID
{
get {return _MasterID;}
set {_MasterID = value;}
}
#endregion MasterID
#region MasterCD
public abstract class masterCD:PX.Data.BQL.BqlString.Field<masterCD> { }
protected string _MasterCD;
[PXDBDefault(typeof(Master.masterCD))]
[PXDBString(IsKey = true, IsUnicode = true)]
public virtual string MasterCD
{
get {return this._MasterCD;}
set {this._MasterCD = value;}
}
#endregion
#region Revision
public abstract class revisionNo:PX.Data.BQL.BqlString.Field<revisionNo> {}
[PXDBString(15, IsKey = true, IsUnicode = true)]
[PXDBDefault(typeof(Master.revisionNo))]
public virtual string RevisionNo { get; set; }
#endregion Revision
public abstract class stepsID:PX.Data.BQL.BqlInt.Field<stepsID> { }
[OperationCDField(IsKey =true, DisplayName = "Steps ID",
Visibility = PXUIVisibility.SelectorVisible)]
[PXDefault(PersistingCheck = PXPersistingCheck.NullOrBlank)]
//[PXUIField(DisplayName = "Process Steps ID")]
public virtual string StepsID { get; set; }
图 - MasterMaint
public class MasterMaint:PXRevisionableGraph<MasterMaint, Master,
Master.masterCD, Master.revisionNo>
{
public PXSelect<Child, Where<Child.masterCD, Equal<Current<Master.masterCD>>,
And<Child.revisionNo, Equal<Current<Master.revisionNo>>>>> ChildRecords;
#region Override
public override bool CanClipboardCopyPaste()
{
return false;
}
public override bool CanCreateNewRevision(MasterMaint fromGraph, MasterMaint toGraph,
string keyValue, string revisionValue, out string error)
{
// Always returns true as new revisions can be created at any time
error = string.Empty;
return true;
}
public override void CopyRevision(MasterMaint fromGraph, MasterMaint toGraph,
string keyValue, string revisionValue)
{
if(toGraph?.Documents?.Current == null || fromGraph?.Documents?.Current == null)
{
// api calls should create new revs on their own - this causes issues
// when calling from api so we need to turn the copy rev logic off
return;
}
toGraph.Documents.Cache.SetDefaultExt<EWPMMasterRouting.status>
(toGraph.Documents.Current);
if(SkipAutoCreateNewRevision())
{
return;
}
CopyChildRecords(fromGraph.Documents.Current.MasterRoutingCD,
fromGraph.Documents.Current.RevisionNo, toGraph.Documents.Current.MasterID,
keyValue, revisionValue, false);
}
internal virtual void CopyChildRecords(string sourceID, string sourceRevisionNo,
int? newMasterID, string newMasterCD, string newRevisionID, bool copyNotes)
{
foreach(Child fromRow in PXSelect<Child,
Where<Child.masterCD, Equal<Required<Child.masterCD>>,
And<Child.revisionNo, Equal<Required<Child.revisionNo>>>>>
.Select(this, sourceID, sourceRevisionNo))
{
var toRow = PXCache<Child>.CreateCopy(fromRow);
toRow.MasterID = newMasterRoutingID;
toRow.ChildID = null;
toRow.MasterCD = newMasterCD;
toRow.RevisionNo= newRevisionID;
toRow = ChildRecords.Insert(toRow);
}
}
#endregion
}
问题 - 当版本中的值发生更改时,记录会显示新的版本号,同时保留 CD 字段与之前的版本和所有子版本一样。
没错,但是保存记录时,出现错误“另一个进程更新了记录,您的更改将会丢失”
为什么会出现错误
在 Acuamtica 中,我们的 NoteID 列在整个系统中是唯一的如果您尝试使用重复的 NoteID 字段值创建记录,您将收到“另一个进程已更新记录”异常,因为它认为您正在更新相同的记录.
在您复制修订版的情况下,您没有重置记录的 NoteID 值,因此您实际上尝试插入具有相同值的另一条记录。
您需要将以下行添加到 CopyRevision 方法
toGraph.Documents.Cache.SetDefaultExt<EWPMMasterRouting.noteID>(toGraph.Documents.Current);
我们有 2 个 DAC - Master 和 Child
主DAC
#region MasterID
public abstract class masterID:PX.Data.BQL.BqlInt.Field<masterID> { }
protected int? _MasterID;
[PXDBIdentity()]
[PXUIField(Visibility = PXUIVisibility.Invisible)]
[PXReferentialIntegrityCheck]
public virtual int? MasterID
{
get {return this._MasterID;}
set {this._MasterID = value;}
}
#endregion
#region MasterCD
public abstract class masterRoutingCD:PX.Data.BQL.BqlString.Field<masterCD> { }
protected string _MasterRoutingCD;
[BomID(DisplayName = "Master #", IsKey = true, Required = true,
Visibility = PXUIVisibility.SelectorVisible)]
[PXDefault]
[Rev.Key(typeof(Setup.pMMasterNumberSequenceID),
typeof(Master.masterCD),
typeof(Master.revisionNo),
typeof(Master.masterCD),
typeof(Master.revisionNo)
)]
public virtual string MasterCD
{
get {return this._MasterCD;}
set {this._MasterCD = value;}
}
#endregion
#region RevisionNo
public abstract class revisionNo:PX.Data.IBqlField { }
protected string _RevisionNo;
[RevisionIDField(IsKey = true, Visibility = PXUIVisibility.SelectorVisible,
Required = true)]
[PXDefault(typeof(Master.defaultRevisionNo),
PersistingCheck = PXPersistingCheck.Nothing)]
[Rev.ID(typeof(Master.defaultRevisionNo),
typeof(Master.masterCD),
typeof(Master.revisionNo),
typeof(Master.revisionNo),
typeof(Master.description),
typeof(Master.fromDate),
typeof(Master.toDate))]
public virtual string RevisionNo
{
get {return this._RevisionNo;}
set {this._RevisionNo = value;}
}
#endregion
子DAC
public abstract class childID:PX.Data.BQL.BqlInt.Field<childID> { }
protected int? _ChildID;
[PXDBIdentity()]
//[PXReferentialIntegrityCheck]
public virtual int? ChildID
{
get {return this._ChildID;}
set {this._ChildID = value;}
}
#endregion
#region MasterID
public abstract class masterID:PX.Data.BQL.BqlInt.Field<masterID> { }
protected int? _MasterID;
[PXDBInt()]
[PXDBDefault(typeof(Master.masterID))]
[PXParent(typeof(Select<Master, Where<Master.masterRoutingCD, Equal<Current<masterCD>>,
And<Master.revisionNo, Equal<Current<revisionNo>>>>>))]
public virtual int? MasterID
{
get {return _MasterID;}
set {_MasterID = value;}
}
#endregion MasterID
#region MasterCD
public abstract class masterCD:PX.Data.BQL.BqlString.Field<masterCD> { }
protected string _MasterCD;
[PXDBDefault(typeof(Master.masterCD))]
[PXDBString(IsKey = true, IsUnicode = true)]
public virtual string MasterCD
{
get {return this._MasterCD;}
set {this._MasterCD = value;}
}
#endregion
#region Revision
public abstract class revisionNo:PX.Data.BQL.BqlString.Field<revisionNo> {}
[PXDBString(15, IsKey = true, IsUnicode = true)]
[PXDBDefault(typeof(Master.revisionNo))]
public virtual string RevisionNo { get; set; }
#endregion Revision
public abstract class stepsID:PX.Data.BQL.BqlInt.Field<stepsID> { }
[OperationCDField(IsKey =true, DisplayName = "Steps ID",
Visibility = PXUIVisibility.SelectorVisible)]
[PXDefault(PersistingCheck = PXPersistingCheck.NullOrBlank)]
//[PXUIField(DisplayName = "Process Steps ID")]
public virtual string StepsID { get; set; }
图 - MasterMaint
public class MasterMaint:PXRevisionableGraph<MasterMaint, Master,
Master.masterCD, Master.revisionNo>
{
public PXSelect<Child, Where<Child.masterCD, Equal<Current<Master.masterCD>>,
And<Child.revisionNo, Equal<Current<Master.revisionNo>>>>> ChildRecords;
#region Override
public override bool CanClipboardCopyPaste()
{
return false;
}
public override bool CanCreateNewRevision(MasterMaint fromGraph, MasterMaint toGraph,
string keyValue, string revisionValue, out string error)
{
// Always returns true as new revisions can be created at any time
error = string.Empty;
return true;
}
public override void CopyRevision(MasterMaint fromGraph, MasterMaint toGraph,
string keyValue, string revisionValue)
{
if(toGraph?.Documents?.Current == null || fromGraph?.Documents?.Current == null)
{
// api calls should create new revs on their own - this causes issues
// when calling from api so we need to turn the copy rev logic off
return;
}
toGraph.Documents.Cache.SetDefaultExt<EWPMMasterRouting.status>
(toGraph.Documents.Current);
if(SkipAutoCreateNewRevision())
{
return;
}
CopyChildRecords(fromGraph.Documents.Current.MasterRoutingCD,
fromGraph.Documents.Current.RevisionNo, toGraph.Documents.Current.MasterID,
keyValue, revisionValue, false);
}
internal virtual void CopyChildRecords(string sourceID, string sourceRevisionNo,
int? newMasterID, string newMasterCD, string newRevisionID, bool copyNotes)
{
foreach(Child fromRow in PXSelect<Child,
Where<Child.masterCD, Equal<Required<Child.masterCD>>,
And<Child.revisionNo, Equal<Required<Child.revisionNo>>>>>
.Select(this, sourceID, sourceRevisionNo))
{
var toRow = PXCache<Child>.CreateCopy(fromRow);
toRow.MasterID = newMasterRoutingID;
toRow.ChildID = null;
toRow.MasterCD = newMasterCD;
toRow.RevisionNo= newRevisionID;
toRow = ChildRecords.Insert(toRow);
}
}
#endregion
}
问题 - 当版本中的值发生更改时,记录会显示新的版本号,同时保留 CD 字段与之前的版本和所有子版本一样。 没错,但是保存记录时,出现错误“另一个进程更新了记录,您的更改将会丢失” 为什么会出现错误
在 Acuamtica 中,我们的 NoteID 列在整个系统中是唯一的如果您尝试使用重复的 NoteID 字段值创建记录,您将收到“另一个进程已更新记录”异常,因为它认为您正在更新相同的记录. 在您复制修订版的情况下,您没有重置记录的 NoteID 值,因此您实际上尝试插入具有相同值的另一条记录。
您需要将以下行添加到 CopyRevision 方法
toGraph.Documents.Cache.SetDefaultExt<EWPMMasterRouting.noteID>(toGraph.Documents.Current);