I am trying to create an entry field to lookup into the workgroups. I have a custom table and I am trying to define the workgroup that is responsible for it. I assumed the PXCompanyTreeSelector would provide the lookup. Is there an attribute I am missing or does the lookup need to be defined separately.
public abstract class responsibleGroup : IBqlField { }
[PXDBInt]
[PXDefault(typeof(EDPartnerInfo.responsibleGroup), PersistingCheck = PXPersistingCheck.NullOrBlank)]
[PX.TM.PXCompanyTreeSelector]
[PXUIField(DisplayName = "Responsible Group", Enabled = false)]
public virtual int? ResponsibleGroup { get; set; }
#endregion
The form formats it as a selector, but the screen only shows a read-only field on execution.
<px:PXSelector ID="edResponsibleGroup" runat="server" DataField="ResponsibleGroup">
</px:PXSelector>
You have set this field to be disabled in this line:
[PXUIField(DisplayName = "Responsible Group", Enabled = false)]
You need to remove Enabled = false from PXUIFieldAttribute.
Related
I'm trying to change the logic that enables the "PO Link" action/button on the Sales Order lines. I'm not finding where the code that controls the enable/disable lives. Is it controlled by a workflow? If so, where?
I've tried the below but the SetEnable() is being overridden, apparently.
public class MySOOrderEntryExt :
PXGraphExtension<PX.Objects.SO.GraphExtensions.SOOrderEntryExt.POLinkDialog,
PX.Objects.SO.GraphExtensions.SOOrderEntryExt.PurchaseSupplyBaseExt, SOOrderEntry>
{
public void _(Events.RowSelected<SOOrder> e)
{
//Base.Actions["pOSupplyOK"].SetEnabled(false); //Doesn't work.
Base.Actions["pOSupplyOK"].SetVisible(false);
}
}
Any ideas would be great.
TIA!
The control consists of 2 components. In the ASPX in the ActionBar of the grid, teh button is defined as:
<px:PXToolBarButton Text="PO Link" DependOnGrid="grid" StateColumn="IsPOLinkAllowed">
<AutoCallBack Command="POSupplyOK" Target="ds" ></AutoCallBack>
</px:PXToolBarButton>
The StateColumn refers to the field that determines if the action/button is enabled or not. This is defined in SOLine in the field IsPOLinkAllowed as:
#region IsPOLinkAllowed
public abstract class isPOLinkAllowed : PX.Data.BQL.BqlBool.Field<isPOLinkAllowed> { }
[PXFormula(typeof(Switch<Case<Where<SOLine.pOCreate, Equal<True>, And<SOLine.operation, Equal<SOOperation.issue>>>, True>, False>))]
[PXUIField(DisplayName = "", Visibility = PXUIVisibility.Invisible, Visible = false, Enabled = false)]
[PXBool]
public virtual bool? IsPOLinkAllowed
{
get;
set;
}
#endregion
The PXFormula indicates that the POCreate field must be true and the operation of the Sales Order be an Issue.
The simplest way to modify this behavior likely is to change the attributes on the field via a DAC extension or CacheAttached in the graph to result in true when you want it enabled.
I have implemented CRM activity on the Custom page where the Key Field is SOOrder Type, SOOrder Nbr & Job Code which are stored in custom DAC. I have tried to add the Entity Type listed on Related Entity and I am not able to figure out how to do it. Pls let me know where to add or override the method to Implement the functionality
The following cod used to implement the CRM Activity
public sealed class SOOrderJobActivities : CRActivityList<PSSOOrderJob>
{
public SOOrderJobActivities(PXGraph graph)
: base(graph) { }
protected override RecipientList GetRecipientsFromContext(NotificationUtility utility, string type, object row, NotificationSource source)
{
var recipients = new RecipientList();
var order = _Graph.Caches[typeof(PSSOOrderJob)].Current as PSSOOrderJob;
if (order == null || source == null)
return null;
SOOrder ord = SOOrder.PK.Find(_Graph, order.OrderType, order.OrderNbr);
var contact = SOOrder.FK.Contact.FindParent(_Graph, ord);
if (contact == null || contact.EMail == null)
return null;
recipients.Add(new NotificationRecipient()
{
Active = true,
AddTo = RecipientAddToAttribute.To,
Email = contact.EMail
});
source.RecipientsBehavior = RecipientsBehaviorAttribute.Override;
return recipients;
}
}
Update
After going through the Acumatica code, I have done the following changes
#region Noteid
[PXNote(ShowInReferenceSelector =true,Selector =typeof(Search2<PSSOOrderJob.jobCode,
InnerJoin<SOOrder,On<PSSOOrderJob.orderType,Equal<SOOrder.orderType>,And<PSSOOrderJob.orderNbr, Equal<SOOrder.orderNbr>>>>,
Where<SOOrder.orderType,Equal<Current<PSSOOrderJob.orderType>>,And<SOOrder.orderNbr, Equal<Current<PSSOOrderJob.orderNbr>>>>>))]
public virtual Guid? Noteid { get; set; }
public abstract class noteid : PX.Data.BQL.BqlGuid.Field<noteid> { }
#endregion
The entity comes into selection, But I am not able to select the relative entity document and the value is not getting updated in the related entity field.
The above screenshot the select is missing and not able to select the document
The following steps I have done to add relative Entity for any Activity using custom DAC
1. Added ShowInReferenceSelector = true in PXNoteID field.
2. Added Selector in PXNoteID field
3. Decorated [PX.Data.EP.PXFieldDescription] attribute for Key fields
#region NoteID
[PXNote(ShowInReferenceSelector = true, Selector = typeof(Search2<PSSOOrderJob.jobCode,
InnerJoin<SOOrder, On<PSSOOrderJob.orderType, Equal<SOOrder.orderType>, And<PSSOOrderJob.orderNbr, Equal<SOOrder.orderNbr>>>>,
Where<SOOrder.orderType, Equal<Current<PSSOOrderJob.orderType>>, And<SOOrder.orderNbr, Equal<Current<PSSOOrderJob.orderNbr>>,And<PSSOOrderJob.jobType,Equal<Current<PSSOOrderJob.jobType>>>>>>), DescriptionField = typeof(PSSOOrderJob.jobCode))]
//[PXNote(ShowInReferenceSelector = true)]
public virtual Guid? NoteID { get; set; }
public abstract class noteID : PX.Data.BQL.BqlGuid.Field<noteID> { }
#endregion
#region JobCode
[PXDBString(15, IsKey = true, IsUnicode = true, InputMask = ">CCCCCCCCCCCCCCC")]
[PXUIField(DisplayName = "Job Code")]
[PXDefault()]
[PXSelector(typeof(Search<PSSOOrderJob.jobCode, Where<PSSOOrderJob.orderType, Equal<Current<PSSOOrderJob.orderType>>, And<PSSOOrderJob.orderNbr, Equal<Current<PSSOOrderJob.orderNbr>>,And<PSSOOrderJob.jobType, Equal<Current<PSSOOrderJob.jobType>>>>>>), typeof(PSSOOrderJob.jobCode), ValidateValue = false)]
[PSSOOrderJobNbr.Numbering()]
[PX.Data.EP.PXFieldDescription]
public virtual string JobCode { get; set; }
public abstract class jobCode : PX.Data.BQL.BqlString.Field<jobCode> { }
#endregion
This automatically fills the related entity field with Jobcode.
There still one issue I am facing is not able to access the selector due to Entity field width is more than the popup window and I do not know how to fix it.
This answer is to address the popup size only.
First, give browser zoom a try 'control' + 'minus' key. It might work as a quick workaround.
Otherwise, use the browser debugger feature. Open it with F12 key. Then use the browser debugger inspect element feature (1). Click on the smart panel (2). Go up a bit in html control hierarchy until you reach and select the smart panel root which is a table element (3). Change the width of the smart panel popup using the debugger CSS properties editor (4).
If selector control size increases automatically with window size; change the selector control width instead of popup width using browser debugger CSS property editor.
I'm customizing the Release Time Activities screen (EP507020) in the following ways:
First, I'm putting the Appointment Number in the grid via the 'Add Data Fields' option in the screen customization.
Second, I want to tie back to the Appointments screen (FS300200) via the Appointment Nbr to get the status.
Third, I want to add a user field to the Time Activities grid to hold this obtained status so that the grid can be filtered by the status.
I've run into several problems, the largest of which is that even though I can add the Appointment Number to the Release Time Activities screen grid - and upon inspection it shows that it belongs to the same DAC as all the other fields in that grid - it show NO WHERE in the DAC when I bring up the source code. It isn't in any table I can find either. This is a complete mystery - how can a field show on the inspection window as part of a DAC when it really isn't?
Next - there are two fields in the DAC for the Appointments screen DAC (FSAppointment) - RefNbr (which is the Appointment Number) and the AppointmentID (which is an auto-incrementing identity field). Which one would I use to tie back to the Appointments screen to link the Appointment Nbr (if that's even possible)?
The main issue is that I cannot find the Appointment Nbr in the DAC (EPActivityApprove) to even tie back to the Appointments screen.
Is this something doable?
The Activity dataview bound to Release Time Activities screen (EP507020) grid contains multiple DACs:
public PXFilteredProcessingJoin<
EPActivityApprove,
EPActivityFilter,
LeftJoin<EPEarningType,
On<EPEarningType.typeCD, Equal<EPActivityApprove.earningTypeID>>,
InnerJoin<EPEmployee,
On<EPEmployee.userID, Equal<EPActivityApprove.ownerID>,
And<Where<EPEmployee.timeCardRequired, NotEqual<True>, Or<EPEmployee.timeCardRequired, IsNull>>>>,
LeftJoin<CRActivityLink,
On<CRActivityLink.noteID, Equal<EPActivityApprove.refNoteID>>,
LeftJoin<CRCase,
On<CRCase.noteID, Equal<CRActivityLink.refNoteID>>,
LeftJoin<CRCaseClass,
On<CRCaseClass.caseClassID, Equal<CRCase.caseClassID>>,
LeftJoin<ContractEx,
On<CRCase.contractID, Equal<ContractEx.contractID>>>>>>>>
[...]
Looking at the main DAC we see it extends PMTimeActivity so it will contain all fields of that DAC too:
public class EPActivityApprove : PMTimeActivity
PMTimeActivity doesn't contain AppointmentID either but another DAC named FSxPMTimeActivity does and it also extends PMTimeActivity. That's the reason why you're seeing that field available in EPActivityApprove:
public class FSxPMTimeActivity : PXCacheExtension<PMTimeActivity>
{
#region AppointmentID
public abstract class appointmentID : PX.Data.IBqlField
{
}
[PXDBInt]
[PXUIField(DisplayName = "Appointment Nbr.")]
[PXSelector(typeof(Search<FSAppointment.appointmentID>),
SubstituteKey = typeof(FSAppointment.refNbr))]
public virtual int? AppointmentID { get; set; }
#endregion
}
Given an EPActivityApprove object I think you can get a reference to the extension containing AppointmentID like this:
EPActivityApprove row = ???;
FSxPMTimeActivity rowExt = row.GetExtension<FSxPMTimeActivity>();
int? appointmentID = rowExt.AppointmentID;
As for the joins, you must specify each key field (IsKey = true) from the DAC.
For FSAppointment these would be SrvOrdType and RefNbr (appointmentID is not a key field in that DAC):
#region SrvOrdType
public abstract class srvOrdType : PX.Data.IBqlField
{
}
[PXDBString(4, IsFixed = true, IsKey = true, InputMask = ">AAAA")]
[PXDefault(typeof(FSSetup.dfltSrvOrdType))]
[PXUIField(DisplayName = "Service Order Type")]
[FSSelectorSrvOrdTypeNOTQuote]
[PX.Data.EP.PXFieldDescription]
public virtual string SrvOrdType { get; set; }
#endregion
#region RefNbr
public abstract class refNbr : PX.Data.IBqlField
{
}
[PXDBString(20, IsKey = true, IsUnicode = true, InputMask = "CCCCCCCCCCCCCCCCCCCC")]
[PXDefault(PersistingCheck = PXPersistingCheck.Nothing)]
[PXUIField(DisplayName = "Appointment Nbr.", Visibility = PXUIVisibility.SelectorVisible, Visible = true, Enabled = true)]
[PXSelector(typeof(
Search2<FSAppointment.refNbr,
LeftJoin<FSServiceOrder,
On<FSServiceOrder.sOID, Equal<FSAppointment.sOID>>,
LeftJoin<Customer,
On<Customer.bAccountID, Equal<FSServiceOrder.customerID>>,
LeftJoin<Location,
On<Location.locationID, Equal<FSServiceOrder.locationID>>>>>,
Where<
FSAppointment.srvOrdType, Equal<Optional<FSAppointment.srvOrdType>>>,
OrderBy<Desc<FSAppointment.refNbr>>>),
new Type[] {
typeof(FSAppointment.refNbr),
typeof(Customer.acctCD),
typeof(Customer.acctName),
typeof(Location.locationCD),
typeof(FSAppointment.docDesc),
typeof(FSAppointment.status),
typeof(FSAppointment.scheduledDateTimeBegin)
})]
[AppointmentAutoNumber(typeof(
Search<FSSrvOrdType.srvOrdNumberingID,
Where<
FSSrvOrdType.srvOrdType, Equal<Optional<FSAppointment.srvOrdType>>>>),
typeof(AccessInfo.businessDate))]
[PX.Data.EP.PXFieldDescription]
public virtual string RefNbr { get; set; }
#endregion
EDIT:
Took a better look at it, I don't think you'll be able to join on the key fields. Because AppointmentID is a Unique Identifier field you can make an exception in this case and join only on that field because it will behave as a single key field.
I am using a PXSelector to choose a contact record. The PXSelector and PXRestrictor works, and I see only active contacts for a particular customer record. However, on the screen it is showing the contact id, hyphen and display name (for example "12345 - Smith, John"). I want it to just show the display name without the id. Here is the code I am using in the DAC:
[PXDBInt()]
[PXUIField(DisplayName = "Billing Contact", Visibility = PXUIVisibility.Visible)]
[PXSelector(typeof(Search2<Contact.contactID,
LeftJoin<BAccount, On<BAccount.bAccountID, Equal<Contact.bAccountID>>>>),
DescriptionField = typeof(Contact.displayName),
Filterable = true,
DirtyRead = true)]
[PXRestrictor(typeof(Where<Contact.contactType, NotEqual<ContactTypesAttribute.bAccountProperty>,
And<WhereEqualNotNull<BAccount.bAccountID, Customer.bAccountID>>>), PX.Objects.CR.Messages.ContactBAccountDiff, typeof(Contact.displayName))]
[PXRestrictor(typeof(Where<Contact.isActive, Equal<True>>), PX.Objects.CR.Messages.ContactInactive, typeof(Contact.displayName))]
public virtual int? UsrBillingContactId { get; set; }
public abstract class usrBillingContactId : IBqlField { }
Thanks in advance for your help!
You need to set the TextField selector property to the Description field.
This value could be 'Contact__DisplayName' for your example
You can use the customization project editor to locate the Description field from the selector joined table:
To set the TextField property you need to show all properties using the funnel button:
I am trying to create a Field to store 'VendorID', in my own DAC.
First I tried using Acumatica attributes to show the selector, like the below
[VendorNonEmployeeActive(Visibility = PXUIVisibility.SelectorVisible, DescriptionField = typeof(Vendor.acctName), CacheGlobal = true, Filterable = true)]
AND
[POVendor(Visibility = PXUIVisibility.SelectorVisible, DescriptionField = typeof(Vendor.acctName), CacheGlobal = true, Filterable = true)]
AND other few attributes. but either it shows employee data or nothing. I even tried to write a selector of my own as below where BAccountRef is a class derived from BAccount.
[PXSelector(typeof(Search2<Vendor.bAccountID,
InnerJoin<BAccountRef, On<Vendor.bAccountID, Equal<BAccountRef.bAccountID>>>,
Where<Vendor.status, Equal<BAccountRef.status.active>,
And<Vendor.type, Equal<BAccountType.vendorType>>>>), new Type[] { typeof(BAccountRef.acctCD), typeof(BAccountRef.acctName) },
SubstituteKey = typeof(BAccountRef.acctCD))]
Unfortunately no luck, from the behaviour, it seems like the records are auto filtered to show employee info. I cant figure out how this is happening. How to make the selector show vendor info? How this is auto filtering the employees in this graph?
Most likely your BQL queries towards Vendor DAC are translated into SQL queries to EPEmployee table. This behavior is caused by the EPEmployee cache (and therefore the BAccount cache) initialized prior to Vendor cache.
Try using PX.Objects.AP.VendorAttribute together with the BAccountR DAC - use of BAccountR will break inheritance between the Vendor and BAccount' DACs and should be translated into SQL queries towardsBAccountandVendor` tables:
[Vendor(typeof(Search<BAccountR.bAccountID,
Where<BAccountR.type, Equal<BAccountType.companyType>,
Or<Vendor.type, NotEqual<BAccountType.employeeType>>>>),
Visibility = PXUIVisibility.SelectorVisible, CacheGlobal = true, Filterable = true)]
[PXRestrictor(typeof(Where<Vendor.status, IsNull,
Or<Vendor.status, Equal<BAccount.status.active>,
Or<Vendor.status, Equal<BAccount.status.oneTime>>>>),
AP.Messages.VendorIsInStatus, typeof(Vendor.status))]
Thanks All,
#Ruslan's answer helped to get the correct definition for the selector. When we use BAccountR or VendorR DAC's the SQL is not translating to EPEmployee and hence i am able to get the correct information.
[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) })]
In one of my recent projects I've used the following in order to get VendorCD:
#region vendor
public abstract class vendor : PX.Data.IBqlField
{
}
protected string _Vendor;
[VendorRaw(typeof(Where<Vendor.vendorClassID, Equal<Current<VendorFilter.vendorClassID>>>),
DescriptionField = typeof(Vendor.acctName), DisplayName = "Vendor ID")]
[PXDefault("", PersistingCheck = PXPersistingCheck.Nothing)]
public virtual string Vendor
{
get
{
return this._Vendor;
}
set
{
this._Vendor = value;
}
}
#endregion
recently I had to add a Vendor Selector on the ExpenseClaimsDetails DAC, after trying several options, this is the one that worked for me:
[PXDBInt()]
[PXUIField(DisplayName = "Vendor", Enabled = true)]
[PXDimensionSelector("VENDOR", typeof(Search<VendorR.bAccountID, Where<VendorR.vStatus, Equal<VendorStatus.active>>>),
typeof(VendorR.acctCD),
new Type[] { typeof(VendorR.acctCD),
typeof(VendorR.acctName),
typeof(VendorR.vendorClassID),
typeof(VendorR.taxRegistrationID)},
Filterable = true,
SelectorMode = PXSelectorMode.TextModeSearch,
DescriptionField = typeof(VendorR.acctName))]
public int? UsrEVVendorID { get; set; }
public abstract class usrEVVendorID : PX.Data.BQL.BqlInt.Field<usrEVVendorID> { }