Update selected failed - acumatica

I use this code to open another screen in SO301000
public virtual IEnumerable EcrListemodele(PXAdapter adapter)
{
var cmdencours = TransactionsOrder.Current;
if (cmdencours==null) return adapter.Get();
ZMODELEFILTER.Current.Immatriculation=cmdencours.GetExtension<SOOrderExt>().UsrImmatriculation;
ZMODELEFILTER.AskExt();
foreach (ZMODELE un_modele in SOZmodele.Select())
{
if (un_modele.Selected == true)
{
cmdencours.GetExtension<SOOrderExt>().Usrlistmodele=un_modele.Modele;
cmdencours.GetExtension<SOOrderExt>().Usrlistpiece=un_modele.Piece;
TransactionsOrder.Update(cmdencours);
}
}
//}
return adapter.Get();
}
I have this error when I select one option
Thanks, Xavier

Make sure that the audit fields use the proper attributes. For example, CreatedByID uses:
#region CreatedByID
public abstract class createdByID : PX.Data.BQL.BqlGuid.Field<createdByID>
{
}
protected Guid? _CreatedByID;
[PXDBCreatedByID()]
public virtual Guid? CreatedByID
{
get
{
return this._CreatedByID;
}
set
{
this._CreatedByID = value;
}
}
#endregion
The attributes you would want to use on the respective fields are:
PXDBCreatedByID
PXDBCreatedByScreenID
PXDBCreatedDateTime
PXDBLastModifiedByID
PXDBLastModifiedByScreenID
PXDBLastModifiedDateTime
PXDBTimestamp

Related

Unbound Field in Standalone Projection

I have a Rich Text field attached to the PMQuote and CRQuote DACs. On the CRQuote, the user field is on the standalone class and the regular class, and that is working as desired. However, Acumatica's reporting does not show the HTML formatting so I am creating an unbound Plain Text field to put on the reports and in GI's. This field works fine on the PMQuote, but not on the CRQuote. On the CRQuote, the field is there, but it is always blank. I'm sure it is something to do with the projection, but I'm not sure how it should be created.
Here is the PMQuote field (working properly)
[PXString(IsUnicode = true)]
[PXUIField(Visible = false, DisplayName = "Scope Text")]
public virtual String UsrScopePlainText
{
get
{
return PX.Data.Search.SearchService.Html2PlainText(UsrScope);
}
}
public abstract class usrScopePlainText : PX.Data.BQL.BqlString.Field<usrScopePlainText> { }
And here is what I have on the CRQuote (not working):
public class CRQuoteExt : PXCacheExtension<CRQuote>
{
#region UsrScope
[PXDBText(IsUnicode = true, BqlField = typeof(CRQuoteStandaloneExt.usrScope))]
[PXUIField(DisplayName = "Scope")]
public virtual string UsrScope { get; set; }
public abstract class usrScope : IBqlField { }
#endregion
#region UsrScopePlainText
[PXString(IsUnicode = true)]
[PXUIField(Visible = false, DisplayName = "Scope Text")]
public virtual String UsrScopePlainText
{
get
{
return PX.Data.Search.SearchService.Html2PlainText(UsrScope);
}
}
public abstract class usrScopePlainText : IBqlField { }
#endregion
}
public class CRQuoteStandaloneExt : PXCacheExtension<PX.Objects.CR.Standalone.CRQuote>
{
#region UsrScope
[PXDBText(IsUnicode = true)]
[PXUIField(DisplayName = "Scope")]
public virtual string UsrScope { get; set; }
public abstract class usrScope : IBqlField { }
#endregion
#region UsrScopePlainText
[PXString(IsUnicode = true)]
[PXUIField(Visible = false, DisplayName = "Scope Text")]
public virtual String UsrScopePlainText
{
get
{
return PX.Data.Search.SearchService.Html2PlainText(UsrScope);
}
}
public abstract class usrScopePlainText : IBqlField { }
#endregion
}
Thanks!
An alternative solution could be to have a reusable attribute that you can attach to any field. I think this is cleaner than adding logic directly in the Data Access class...
using PX.Objects.IN;
using PX.Data;
using System;
namespace PX.Objects.IN
{
public class InventoryItemPlainTextBodyExt : InventoryItem
{
[HtmlToText(typeof(InventoryItem.body))]
[PXDependsOnFields(typeof(InventoryItem.body))]
[PXUIField(DisplayName="Body (Plain Text)")]
public virtual string BodyPlainText { get; set; }
public abstract class bodyPlainText : PX.Data.BQL.BqlString.Field<bodyPlainText> { }
}
[PXString]
public class HtmlToTextAttribute : PXEventSubscriberAttribute, IPXFieldSelectingSubscriber
{
protected Type _htmlField;
public HtmlToTextAttribute(Type htmlField) :base()
{
_htmlField = htmlField;
}
public void FieldSelecting(PXCache sender, PXFieldSelectingEventArgs e)
{
e.ReturnValue = PX.Data.Search.SearchService.Html2PlainText(sender.GetValue(e.Row, _htmlField.Name) as string);
}
}
}
I'm not sure what happened, but I put the original code I posted above back into the customization project and it started working as expected.

Acumatica - Revision

We have 2 DAC - Master and Child
Master 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
Child 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; }
Graph - 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
}
Issue - When the value is changed in the Revision the record is displayed with new revision number keeping the CD fields as for previous revision and all the child.
That is all correct, But when the record is saved, there is error "Another process has updated the Record, your changes will be lost"
Why there is a Error
In Acuamtica we have NoteID column unique across the system If you try to create a record with duplicating NoteID field value you'll get "Another process has updated the record" exception because it consider that you are updating the same record.
In you case when you copy revision you do not reset the NoteID value for the record so you actually try to insert another record with the same value.
You'll need to add the following line to CopyRevision method
toGraph.Documents.Cache.SetDefaultExt<EWPMMasterRouting.noteID>(toGraph.Documents.Current);

How to save a record with two fields disabled on the PM301000 screen

Good afternoon everyone,
I need your help, I want to record one or several records on the PM301000 Projects screen in the detail tab, Cost Budget.
When recording one or more records, two Mark for PO and Vendor ID fields must be disabled. When the condition of the Mark for PO field is equal to true.
I have used the RowPersisting event and it disables it but when I modify or leave the registry the fields are enabled again.
Please help me or tell me how I should do it, my code is as follows.
Thanks in advance.
namespace PX.Objects.PM
{
public class PMBudgetExt : PXCacheExtension<PX.Objects.PM.PMBudget>
{
#region UsrVendorID
[PXDBInt]
[PXUIField(DisplayName = "Vendor ID", Visibility = PXUIVisibility.Visible)]
[PXDimensionSelectorAttribute("VENDOR", typeof(Search<VendorR.bAccountID, Where<VendorR.type, Equal<BAccountType.vendorType>,
And<VendorR.status, Equal<BAccount.status.active>>>>),
typeof(VendorR.acctCD), new Type[] { typeof(VendorR.acctCD), typeof(VendorR.acctName) })]
public virtual int? UsrVendorID { get; set; }
public abstract class usrVendorID : PX.Data.BQL.BqlInt.Field<usrVendorID> { }
#endregion
#region UsrMarkforPO
[PXDBBool()]
[PXDefault(false)]
[PXUIField(DisplayName = "Mark for PO")]
public virtual bool? UsrMarkforPO { get; set; }
public abstract class usrMarkforPO : PX.Data.BQL.BqlBool.Field<usrMarkforPO> { }
#endregion
}
}
namespace PX.Objects.PM
{
public class ProjectEntry_Extension : PXGraphExtension<ProjectEntry>
{
#region Event Handlers
protected void PMCostBudget_RowPersisting(PXCache cache, PXRowPersistingEventArgs e)
{
PMCostBudget newRow = (PMCostBudget)e.Row;
if (newRow == null) return;
PMBudgetExt newRowE = PXCache<PMBudget>.GetExtension<PMBudgetExt>(newRow);
if (Base.CostBudget.Cache.AllowUpdate == true)
{
if (newRowE.UsrMarkforPO == true)
{
PXUIFieldAttribute.SetEnabled<PMBudgetExt.usrMarkforPO>(cache, newRow, false);
PXUIFieldAttribute.SetEnabled<PMBudgetExt.usrVendorID>(cache, newRow, false);
}
}
}
#endregion
}
}
RowPersisting event executes only on save event. Therefore it's not suited for setting the field states. You will get better results with RowSelected event which is executed everytime a record is selected to be displayed on screen. You should set the state on every callback whether it is enabled or disabled. Also, the event should be declared on the same DAC type you are using to set the field state so the cache object match.
public void PMBudget_RowSelected(PXCache sender, PXRowSelectedEventArgs e, PXRowSelected del)
{
if (del != null)
{
del(sender, e);
}
bool isFieldEnabled = [your_condition];
PXUIFieldAttribute.SetEnabled<PMBudget.field>(sender, e.Row, isFieldEnabled);
}

Is it possible to dynamically change the PXSelect a view is using programatically?

I have a button in which, when pressed, I want to show or hide rows in a grid based on certain criteria. Is it possible to change the PXSelect a view uses on the fly so that it re-queries the database and retrieves different results? I will, of course, be querying the same table and not changing up the structure of the View or grid.
The code below adds a non-visible field to the header record that is set by the button press this value is then used by the child records view delegate to determine based on the child records criteria (in this case a Boolean on each child) if they are shown.
public sealed class APInvoiceExtension : PXCacheExtension<APInvoice>
{
#region UsrShowAll
public abstract class usrShowAll : IBqlField
{
}
[PXBool]
public bool? UsrShowAll { get; set; }
#endregion
}
public sealed class APTranExtension : PXCacheExtension<APTran>
{
#region UsrHidden
public abstract class usrHidden : IBqlField
{
}
[PXDBBool]
[PXUIField(DisplayName = "Hidden", Enabled = false)]
public bool? UsrHidden { get; set; }
#endregion
}
public class APInvoiceEntryExtension : PXGraphExtension<APInvoiceEntry>
{
public PXAction<APInvoice> SHW;
[PXUIField(DisplayName = "Show All Records", MapEnableRights = PXCacheRights.Update, MapViewRights = PXCacheRights.Update)]
[PXButton]
protected void sHW()
{
if (Base.Document.Current != null)
{
APInvoiceExtension docExt = Base.Document.Current.GetExtension<APInvoiceExtension>();
docExt.UsrShowAll = !(docExt.UsrShowAll ?? false);
}
}
protected virtual IEnumerable transactions()
{
bool showAll = Base.Document.Current != null ? (Base.Document.Current.GetExtension<APInvoiceExtension>().UsrShowAll ?? false) : false;
APTran tran;
foreach (PXResult<APTran, POReceiptLine> res in Base.Transactions.Select())
{
tran = res[0] as APTran;
if (!showAll)
{
if (!(tran.GetExtension<APTranExtension>().UsrHidden ?? false))
{
yield return res;
}
}
else
{
yield return res;
}
}
}
}

Acumatica Add Filter on Create Requisition Screen

May I ask for your guidance here, my problem is I added a Branch Filter on the Create Requisition(RQ504000) screen, I tried to override the RQRequestProcessing Class but it just don't work. I also tried adding a WhereAnd on the Records view upon field updated but it also does not work. Any suggestion is greatly appreciated thanks.
I propose you following solution:
public class RQRequestSelectionExt : PXCacheExtension<RQRequestSelection>
{
#region AllocatedAmount2
public abstract class usrBranchID : IBqlField
{
}
[PXDBInt]
[PXUIField(DisplayName = "Branch ID")]
[PXDefault(2)]
[Branch]
public int? UsrBranchID { get; set; }
#endregion
}
public class RQRequestProcessExt : PXGraphExtension<RQRequestProcess>
{
[PXFilterable(new System.Type[] { })]
public RQRequestProcess.RQRequestProcessing Records;
public IEnumerable records()
{
var currentFilter = Base.Filter.Current;
var filterExt = currentFilter.GetExtension<RQRequestSelectionExt>();
var newList = Base.Records.Select();
ArrayList result = new ArrayList();
foreach (PXResult<RQRequestLineOwned> listItme in newList)
{
var row = listItme.GetItem<RQRequestLineOwned>();
if (filterExt.UsrBranchID != null)
{
if (row.BranchID == filterExt.UsrBranchID)
{
result.Add(row);
}
}
else
{
result.Add(row);
}
}
return result;
}
}
Another one, you can try to play with WhereAnd, but I for myself wasn't very successful with it.

Resources