so I'm trying to add a small bool field to the SOInvoiceEntry graph, so it can be exposed to the API. It needs to remain editable even after the document has been closed and released. I've set up the DAC field as:
public class ARRegisterExt : PXCacheExtension<PX.Objects.AR.ARRegister>
{
[PXDBBool]
[PXUIField(DisplayName="Has been integrated", Visibility = PXUIVisibility.Visible, Enabled = true)]
public virtual bool? UsrIsIntegrated { get; set; }
public abstract class usrIsIntegrated : IBqlField { }
}
And added RowSelected events which should, in theory, be setting the field to enabled:
public class SOInvoiceEntry_Extensions : PXGraphExtension<SOInvoiceEntry>
{
[PXOverride]
public void SOInvoice_RowSelected(PXCache sender, PXRowSelectedEventArgs e, PXRowSelected baseMethod)
{
baseMethod?.Invoke(sender, e);
if (e.Row == null) return;
PXUIFieldAttribute.SetEnabled<ARRegisterExt.usrIsIntegrated>(sender, e.Row, true);
}
}
However the field remains readonly on closed invoices. I've tested this on the ARInvoiceEntry graph, and exposed that to the api, and it works fine. I've been testing different methods of setting the field as enabled, but no luck so far.
Any help would be awesome.
Thanks
Issue was caused by an automation step on the SOInvoiceEntry screen setting the ARInvoice table as disabled, which was overriding the logic I was adding.
Related
I have added custom fields in customization form using the customization form, steps i have added:
1) Go to shipment form and select Transaction Grid.
2) Select Add fields.
3) Select custome and Add 4 fields and save and publish.
4) Add all 4 fields and select used and save.
5) and publish again and all 4 columns are visible.
6) I have added a user fields name Aloow (PXDBBool), UsrPClocation(Location) and UsrPCwarehouse(Site),
and i set the below attribute in warehour and location.
7) But on SOSHipLine_InventotyID_FieldUpdate event, i am setting Allow, location, warehouse all 3 values, but values are not showing in Grid, what is the resoon?
#region UsrQCSiteID
[PXUIField(DisplayName = "PC Warehouse")]
[SiteAvail(typeof(SOShipLine.inventoryID), typeof(SOShipLine.subItemID))]
[PXUIRequired(typeof(Where<usrAllow, Equal<True>>))]
[PXUIEnabled(typeof(Where<usrAllow, Equal<True>>))]
[PXDefault()]
public virtual int? UsrPCSiteID {
get; set;
}
public abstract class usrPCSiteID:PX.Data.BQL.BqlInt.Field<usrPCSiteID> {
}
#endregion UsrPCSiteID
#region UsrPCLocationID
[PXUIField(DisplayName = "PC Location")]
[SOLocationAvail(typeof(SOShipLine.inventoryID), typeof(SOShipLine.subItemID), typeof(SOShipLineExt.usrPCSiteID), typeof(SOLine.tranType), typeof(SOShipLine.invtMult))]
[PXUIRequired(typeof(Where<usrQCRequired, Equal<True>>))]
[PXUIEnabled(typeof(Where<usrQCRequired, Equal<True>>))]
[PXDefault()]
public virtual int? UsrPCLocationID {
get; set;
}
public abstract class usrPCLocationID:PX.Data.BQL.BqlInt.Field<usrPCLocationID> {
}
#endregion UsrPCLocationID
#region Allow
[PXDBBool]
[PXUIField(DisplayName = "Allow")]
public virtual bool? UsrAllow {
get; set;
}
public abstract class usrAllow:PX.Data.BQL.BqlBool.Field<usrAllow> {
}
#endregion
IS SOShipLine allow updating custom values?
The steps that you described look correct.
I recreated this scenario locally:
1 - My DAC extension looks as follows:
public class SOShipLineExt : PXCacheExtension<PX.Objects.SO.SOShipLine>
{
#region UsrPCSiteID
[PXUIField(DisplayName = "PC Warehouse")]
[SiteAvail(typeof(SOShipLine.inventoryID), typeof(SOShipLine.subItemID))]
public virtual int? UsrPCSiteID {
get; set;
}
public abstract class usrPCSiteID:PX.Data.BQL.BqlInt.Field<usrPCSiteID> {
}
#endregion UsrPCSiteID
#region UsrPCLocationID
[PXUIField(DisplayName = "PC Location")]
[SOLocationAvail(typeof(SOShipLine.inventoryID), typeof(SOShipLine.subItemID), typeof(SOShipLineExt.usrPCSiteID), typeof(SOShipLine.tranType), typeof(SOShipLine.invtMult))]
public virtual int? UsrPCLocationID {
get; set;
}
public abstract class usrPCLocationID:PX.Data.BQL.BqlInt.Field<usrPCLocationID> {
}
#endregion UsrPCLocationID
#region Allow
[PXDBBool]
[PXUIField(DisplayName = "Allow")]
public virtual bool? UsrAllow {
get; set;
}
public abstract class usrAllow:PX.Data.BQL.BqlBool.Field<usrAllow> {
}
#endregion
}
Notes about the DAC Extension:
I removed references to PXUIEnabled and PXUIRequired. If you are looking to disable the Site and the Location based on the checkbox's value, I recommend you manage this logic in the RowSelected event. (it may be feasible with your approach but I have not used it before)
The PXDefault references were also removed, given that in most cases the Shipment is created directly from the Sales Order page. As you have it right now, the field is mandatory but no default value is being assigned which will cause an error. You have 2 options: 1) indicate the value in the PXDefault() attribute, or 2) Set the property PXPersistingCheck.Nothing.
Note that your SOLocationAvail attribute has an error in the 4th parameter. You should use typeof(SOShipLine.tranType) instead of typeof(SOLine.tranType). This was generating an error when the shipment was created from the SO.
2 - My FieldUpdated event looks as follows:
public class SOShipmentEntry_Extension : PXGraphExtension<SOShipmentEntry>
{
protected virtual void SOShipLine_InventoryID_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e)
{
if (e.Row == null) return;
SOShipLine line = (SOShipLine)e.Row;
SOShipLineExt lineExt = cache.GetExtension<SOShipLineExt>(line);
if (lineExt != null)
{
lineExt.UsrAllow = true;
lineExt.UsrPCSiteID=154;
lineExt.UsrPCLocationID=155;
}
}
}
Notes about the Graph extension:
I hard-coded the Warehouse and Location values. I recommend you do the same on your end while testing is being done, just make sure that the IDs exist in your DB, or that you query the CD value and then use its corresponding ID value.
Results:
When the Shipment is created from a SO, the values are being correctly assigned:
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);
}
I want to show which user created Invoice, for this i have added default Acumatica field, but the label is showing as Created By, how can i change that label name to "Invoice Created By". Please have a look at below screenshot for field am referring to.
You could use PXUIFieldAttribute.SetDisplayName static method to change DAC field’s display name. This change will be applicable only for Sales Invoice Entry Graph (SO303000 screen)
public class SOInvoiceEntryPXDemoExt : PXGraphExtension<SOInvoiceEntry>
{
public override void Initialize()
{
PXUIFieldAttribute.SetDisplayName<ARInvoice.createdByID>(Base.Document.Cache, "Invoice Created By");
}
}
If you need display name changed for this field in all screens, you need to have DAC Extension as below:
With this, attributes specified in an extension DAC apply to DAC class in every Graph of the application unless a Graph replaces them with other attributes.
public class ARInvoicePXDemoExt : PXCacheExtension<ARInvoice>
{
[PXMergeAttributes(Method = MergeMethod.Append)]
[PXUIField(DisplayName = "Invoice Created By", Enabled = false, IsReadOnly = true)]
public virtual Guid? CreatedByID { get; set; }
}
You need to add CreatedByID field on screen SO303000
And set DisplayMode property to Text.
The 'CreatedByID' I believe is an audit field and therefore cannot easily change the ui of the additional data fields available through the control. The resolution I would suggest is a non database backed UI field that is populated during row selecting. Example can be found below :
public class SOOrderEntryExtension : PXGraphExtension<SOOrderEntry>
{
public virtual void SOOrder_RowSelecting(PXCache sender, PXRowSelectingEventArgs e)
{
SOOrder row = e.Row as SOOrder;
if(row != null)
{
SOOrderExtension rowExt = PXCache<SOOrder>.GetExtension<SOOrderExtension>(row);
Users user = PXSelectReadonly<Users, Where<Users.pKID, Equal<Required<Users.pKID>>>>.Select(this.Base, row.CreatedByID);
if(user != null)
{
rowExt.InvoiceCreatedBy = user.DisplayName;
}
}
}
}
public class SOOrderExtension : PXCacheExtension<SOOrder>
{
public abstract class invoiceCreatedBy : PX.Data.IBqlField
{
}
[PXString]
[PXUIField(DisplayName = "Invoice Created By")]
public virtual string InvoiceCreatedBy { get; set; }
}
I was asked to make what I thought would be a very simple customization, hide the Promised On field on the PO Order Entry page. I opened the PO301000 screen in the customization editor, highlighted Promised On, clicked Attributes and clicked Override on Screen Level. I changed the resulting code on POOrderEntry to:
namespace PX.Objects.PO
{
public class POOrderEntry_Extension : PXGraphExtension<POOrderEntry>
{
#region Event Handlers
[PXDBDate()]
[PXDefault(typeof(POOrder.orderDate), PersistingCheck = PXPersistingCheck.Nothing)]
[PXUIField(DisplayName = "Promised On", Visibility = PXUIVisibility.Visible, Visible = false)]
protected virtual void POOrder_ExpectedDate_CacheAttached(PXCache cache)
{
}
#endregion
}
}
To my surprise, it did not work, the Promised On field is still visible and I do not know why. The version is 18.100.0062.
It looks like there is a RowSelected event in POOrderEntry that sets the visibility based on if it is a blanket PO. Since this is later in the chain of events it overrides the CacheAttached event.
You can get what you want by adding your own RowSelected event. Here's an example.
protected void POOrder_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
{
PXUIFieldAttribute.SetVisible<POOrder.expectedDate>(cache, null, false);
}
GeorgeM use the code below. The trick is to call baseMethod before making changes to the visible state of the field.
namespace PX.Objects.PO
{
public class POOrderEntry_Extension : PXGraphExtension<POOrderEntry>
{
[PXOverride]
protected virtual void POOrder_RowSelected(PXCache cache, PXRowSelectedEventArgs e, PXRowSelected baseMethod)
{
baseMethod(cache, e);
PXUIFieldAttribute.SetVisible<POOrder.expectedDate>(cache, null, false);
}
}
}
How can I show QtyOnHand in IN402000 to the PO 301000 detail grid?
The POLine DAC already has a "QtyAvail (Qty on Hand)" field. You would simply need to create a customization project, add the screen, navigate to the Grid: Transactions and add the Control for the field to the screen & publish.
If you need to add the field to PO Line and the Quantity Available from INItemStatus would suffice you could add it with:
using System;
using PX.Data;
using PX.Objects.PO;
using PX.Objects.IN;
public class POLine_Extension : PXCacheExtension<POLine> {
[PXDecimal]
[PXUIField(DisplayName = "Qty Avail", Enabled = false)]
[PXDBScalar(typeof(
Search<INSiteStatus.qtyAvail,
Where<INSiteStatus.inventoryID, Equal<POLine.inventoryID>,
And<INSiteStatus.siteID, Equal<POLine.siteID>>>>))]
public virtual decimal? QtyAvail { get; set; }
public abstract class qtyAvail : IBqlField {}
}
Then the PXDBScalar fields have their values set when the DAC is Selected. There's probably a better way this could be done, but to populate the field as lines are added & updated to the PO within a POOrderEntry graph extension, you could handle the FieldUpdated events for the InventoryID and SiteID to execute a function that retrieves the Qty Available using basically the same BQL and sets that value to the DAC extension field.
public class POOrderEntry_Extension : PXGraphExtension<POOrderEntry>
{
public virtual void POLine_InventoryID_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e)
{
UpdateQtyAvailable(sender, e);
}
public virtual void POLine_SiteID_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e)
{
UpdateQtyAvailable(sender, e);
}
private void UpdateQtyAvailable(PXCache sender, PXFieldUpdatedEventArgs e)
{
if (e.Row == null) return;
POLine row = (POLine)e.Row;
foreach(INSiteStatus siteStatus in PXSelect<INSiteStatus,
Where<INSiteStatus.inventoryID, Equal<Required<INSiteStatus.inventoryID>>,
And<INSiteStatus.siteID, Equal<Required<INSiteStatus.siteID>>>>>.Select(sender.Graph, row.InventoryID, row.SiteID))
{
sender.SetValueExt<POLine_Extension.qtyAvail>(row, siteStatus.QtyAvail);
}
}
}