Acumatica - Attempting to add INItemXRef AlternatID to universal search.
I did look at another question that seemed to possibly be a duplicate of my question, but Acumatica gave him a different approach and he has not gotten any responses, hoping to have better luck:
Adding INItemXRef to Global Search with Inventory Item
The goal is a universal search by customer item number. Acumatica advised to create a dummy INItemXRef maintenance screen and add a searchable NoteID to the DAC to reference this screen. Below is my first stab at adding the NoteID, but I'm getting compilation errors:
public class INItemXRefExt : PXCacheExtension<PX.Objects.IN.INItemXRef>
{
#region NoteID
[PXDBGuid]
[PXUIField(DisplayName="NoteID")]
[PXSearchable(SM.SearchCategory.IN,
"{0}: {1}",
new Type[] { typeof(INItemXRef.alternateType), typeof(INItemXRef.inventoryID)},
new Type[] { typeof(INItemXRef.descr), typeof(INItemXRef.alternateID) }, // add fields you want to be searchable
NumberFields = new Type[] { typeof(INItemXRef.inventoryID) },
Line1Format = "{0}{1}", Line1Fields = new Type[] { typeof(INItemClass.itemClassCD), typeof(INItemXRef.alternateID)},
Line2Format = "{0}", Line2Fields = new Type[] { typeof(INItemXRef.descr) },
//WhereConstraint = typeof(Where<Current<InventoryItem.itemStatus>, NotEqual<InventoryItemStatus.unknown>>),
SelectForFastIndexing = typeof(Select<INItemXRef>) // this is required so that search knows how to index your fields
)]
//[PXNote(PopupTextEnabled = true)]
//public Guid? NoteID { get; set; }
public virtual Guid? NoteID { get; set; }
public abstract class NoteID : IBqlField { }
#endregion
}
When compiling I get this validation error:
\App_RuntimeCode\INItemXRef.cs(28): error CS0102: The type 'PX.Objects.IN.INItemXRefExt' already contains a definition for 'NoteID'
I thought at first that the reason is because the field was already created in a previous run (I think it was), and the public abstract class NoteID : IBqlField { } was essentially trying to get it to duplicate the field. So I commented out the line and got this:
The base property is missed or IBqlField is not defined: NoteID in extension PX.Objects.IN.INItemXRefExt
I'm sure there are plenty of problems with my searchable attribute as well and will update the question as it evolves, but for the moment I'm stumped at the compilation step.
Update:
Thanks to the responses below I was able to re-write a bit and get everything to compile. Next step is to figure out why the results are a bit strange. interestingly, I cannot do a universal search and find any item unless it has a cross-reference, and then only displays base item info even though I'm trying to display the alternate code(s) and descriptions(s). New code:
#region NoteID
public abstract class noteID : PX.Data.IBqlField
{
}
protected Guid? _NoteID;
[PXSearchable(SM.SearchCategory.IN,
"{0}: {1}",
new Type[] { typeof(INItemXRef.alternateType), typeof(INItemXRef.inventoryID)},
new Type[] { typeof(INItemXRef.descr), typeof(INItemXRef.alternateID) }, // add fields you want to be searchable
NumberFields = new Type[] { typeof(INItemXRef.inventoryID) },
Line1Format = "{0}{1}", Line1Fields = new Type[] { typeof(INItemClass.itemClassCD), typeof(INItemXRef.alternateID)},
Line2Format = "{0}", Line2Fields = new Type[] { typeof(INItemXRef.descr) },
//WhereConstraint = typeof(Where<Current<InventoryItem.itemStatus>, NotEqual<InventoryItemStatus.unknown>>),
SelectForFastIndexing = typeof(Select<INItemXRef>) // this is required so that search knows how to index your fields
)]
[PXNote(DescriptionField = typeof(INItemXRef.inventoryID),
Selector = typeof(INItemXRef.inventoryID))]
public virtual Guid? NoteID
{
get
{
return this._NoteID;
}
set
{
this._NoteID = value;
}
}
#endregion
You can review one of the out-of-the-box DAC that contains NoteID field and review it for guidance. For example, take a look at the INRegister.NoteID field definition:
#region NoteID
public abstract class noteID : PX.Data.IBqlField
{
}
protected Guid? _NoteID;
[PXSearchable(SM.SearchCategory.IN, "{0}: {1}", new Type[] { typeof(INRegister.docType), typeof(INRegister.refNbr) },
new Type[] { typeof(INRegister.tranDesc), typeof(INRegister.extRefNbr), typeof(INRegister.transferNbr) },
NumberFields = new Type[] { typeof(INRegister.refNbr) },
Line1Format = "{0}{1:d}{2}{3}{4}", Line1Fields = new Type[] { typeof(INRegister.extRefNbr), typeof(INRegister.tranDate), typeof(INRegister.transferType), typeof(INRegister.transferNbr), typeof(INRegister.status) },
Line2Format = "{0}", Line2Fields = new Type[] { typeof(INRegister.tranDesc) },
WhereConstraint = typeof(Where<INRegister.docType, NotEqual<INDocType.production>, And<INRegister.docType, NotEqual<INDocType.disassembly>>>)
)]
[PXNote(DescriptionField = typeof(INRegister.refNbr),
Selector = typeof(INRegister.refNbr))]
public virtual Guid? NoteID
{
get
{
return this._NoteID;
}
set
{
this._NoteID = value;
}
}
#endregion
Notice the use of PXNote attribute(and no use of PXDBGuid attribute).
You can try similar approach and only with PXNote first, to confirm it compiles properly. Then you could add PXSearcheable and start working on it.
This particular question has been answered, but in order to get the search to work the way I need will have to go a different direction creating a brand-new DAC, BLC, and maintenance screen. Thanks for the help!
Related
I added a few user defined fields to StockItem recently, added values to a few records, then attempted to search by value for them. The search engine is not aware of my UDF values unfortunately.
Is there a way to have user defined fields searchable?
Yes, as Brian indicated we need to add a PXSearchable attribute for the NoteID field of that particular DAC. The below code from the SOOrder DAC file and it may help you to achieve your requirement.
#region NoteID
public abstract class noteID : PX.Data.BQL.BqlGuid.Field<noteID> { }
protected Guid? _NoteID;
[**PXSearchable**(SM.SearchCategory.SO, "{0}: {1} - {3}", new Type[] { typeof(SOOrder.orderType), typeof(SOOrder.orderNbr), typeof(SOOrder.customerID), typeof(Customer.acctName) },
new Type[] { typeof(SOOrder.customerRefNbr), typeof(SOOrder.customerOrderNbr), typeof(SOOrder.orderDesc) },
NumberFields = new Type[] { typeof(SOOrder.orderNbr) },
Line1Format = "{0:d}{1}{2}{3}", Line1Fields = new Type[] { typeof(SOOrder.orderDate), typeof(SOOrder.status), typeof(SOOrder.customerRefNbr), typeof(SOOrder.customerOrderNbr) },
Line2Format = "{0}", Line2Fields = new Type[] { typeof(SOOrder.orderDesc) },
MatchWithJoin = typeof(InnerJoin<Customer, On<Customer.bAccountID, Equal<SOOrder.customerID>>>),
SelectForFastIndexing = typeof(Select2<SOOrder, InnerJoin<Customer, On<SOOrder.customerID, Equal<Customer.bAccountID>>>>)
)]
[PXNote(new Type[0], ShowInReferenceSelector = true, Selector = typeof(
Search2<
SOOrder.orderNbr,
LeftJoinSingleTable<Customer,
On<SOOrder.customerID, Equal<Customer.bAccountID>,
And<Where<Match<Customer, Current<AccessInfo.userName>>>>>>,
Where<
Customer.bAccountID, IsNotNull,
Or<Exists<
Select<
SOOrderType,
Where<
SOOrderType.orderType, Equal<SOOrder.orderType>,
And<SOOrderType.aRDocType, Equal<ARDocType.noUpdate>>>>>>>,
OrderBy<
Desc<SOOrder.orderNbr>>>))]
public virtual Guid? NoteID
{
get
{
return this._NoteID;
}
set
{
this._NoteID = value;
}
}
#endregion
User requirement is to add universal search for the new screen, added our new screen under Inventory Module also the new screen is not entry screen it is just like user view screen so in that DAC for note id field we have added searchable attribute but it does not work.
Can someone please help me with sample code or correct me where i am doing wrong.
Also let me know is it possible to add searchable attribute for the new screens or not in Acumatica?
Thanks in advance.
#region Noteid
public new abstract class noteid : PX.Data.BQL.BqlGuid.Field<noteid> { }
protected Guid? _Noteid;
[PXSearchable(PX.Objects.SM.SearchCategory.All , "{0}", new Type[] { typeof(KWLotSerialDetails.lotSerialNbr) },
new Type[] { typeof(KWLotSerialDetails.lotSerialNbr), typeof(KWLotSerialDetails.inventoryID)},
NumberFields = new Type[] { typeof(KWLotSerialDetails.lotSerialNbr) },
Line1Format = "{0}{1}", Line1Fields = new Type[] { typeof(KWLotSerialDetails.lotSerialNbr), typeof(KWLotSerialDetails.inventoryID)},
Line2Format = "{1}{2}", Line2Fields = new Type[] { typeof(KWLotSerialDetails.lotSerialNbr), typeof(KWLotSerialDetails.inventoryID) })]
public virtual Guid? Noteid
{
get
{
return this._Noteid;
}
set
{
this._Noteid = value;
}
}
#endregion
You absolutely can add universal search to custom tables. Search is added to a DAC, not a screen, so it doesn't matter about using in a "user view screen". When the full-text index is rebuilt, your NoteID field is processed into the SearchIndex table.
I may be wrong, but I also think you need to convert your Noteid field to NoteID/noteID for this to work properly. C# is case sensitive, and FullIndexRebuild.cs contains:
entity.GetNestedType("noteID")
... so I think it is not finding your Noteid/noteid field because of this.
One of my custom PXSearchable NoteID fields:
#region NoteID
[PXNote]
[PXSearchable(PX.Objects.SM.SearchCategory.IN, "{0}",
new Type[] { typeof(SSINItemManufacturer.manufacturerItem) },
new Type[] { typeof(SSINItemManufacturer.manufacturerItem) },
NumberFields = new Type[] { typeof(SSINItemManufacturer.manufacturerItem) },
Line1Format = "{0}", Line1Fields = new Type[] { typeof(SSINItemManufacturer.manufacturerItem) },
Line2Format = "{0}", Line2Fields = new Type[] { typeof(SSINItemManufacturer.manufacturerItem) },
WhereConstraint = typeof(Where<Current<SSINItemManufacturer.isActive>, NotEqual<False>>),
MatchWithJoin = typeof(InnerJoin<InventoryItem, On<InventoryItem.inventoryID, Equal<SSINItemManufacturer.inventoryID>>>),
SelectForFastIndexing = typeof(Select2<SSINItemManufacturer, InnerJoin<InventoryItem, On<SSINItemManufacturer.inventoryID, Equal<InventoryItem.inventoryID>>>>)
)]
public virtual Guid? NoteID { get; set; }
public abstract class noteID : PX.Data.BQL.BqlGuid.Field<noteID> { }
#endregion
Also check that your DAC is "known" by the "Rebuild Full-Text Entity" screen. Check screen SM209500 to make sure your DAC is listed, and if so, try rebuilding the full-text index on it.
I am trying to add INItemXRef's Alternate ID to the global search for Inventory Item profiles. This is a 1:many relationship since there can be various vendors and units of measure with different Alternate ID's.
Per Acumatica, I have tried replacing the NoteID for Inventory Item with a match with join with the below code:
[PXSearchable(SM.SearchCategory.IN, "{0}: {1}", new Type[] {
typeof(InventoryItem.itemType), typeof(InventoryItem.inventoryCD) },
new Type[] { typeof(InventoryItem.descr) },
NumberFields = new Type[] { typeof(InventoryItem.inventoryCD) },
Line1Format = "{0}{1}{2}", Line1Fields = new Type[] {
typeof(INItemClass.itemClassCD), typeof(INItemClass.descr),
typeof(INItemXRef.alternateID) },
Line2Format = "{0}", Line2Fields = new Type[] {
typeof(InventoryItem.descr)},
MatchWithJoin = typeof(RightJoin<INItemXRef, On<INItemXRef.inventoryID,
Equal<InventoryItem.inventoryID>>>),
WhereConstraint = typeof(Where<Current<InventoryItem.itemStatus>,
NotEqual<InventoryItemStatus.unknown>>)
)]
[PXNote(PopupTextEnabled = true)]
I've also followed the example from question How to include field from a linked entity into Full-Text Entity Index?
My code for this in Inventory Item's DAC extension is:
public partial class INItemXRef: PX.Data.IBqlTable
{
//, IPaymentTypeDetailMaster, ILocation
public abstract class inventoryID: IBqlField { }
[PXDBInt()]
[PXDBChildIdentity(typeof(INItemXRef.inventoryID))]
[PXUIField(DisplayName = "Xref ID", Visibility = PXUIVisibility.Invisible)]
[PXSelector(typeof(Search<INItemXRef.inventoryID>), DirtyRead = true)]
public virtual int? InventoryID{ get; set; }
//public virtual void InventoryItem_InventoryID_CacheAttached(PXCache sender)
//{
//}
public abstract class alternateID: IBqlField { }
[PXDBString()]
[PXUIField(DisplayName = "Alternate ID")]
public virtual int? AlternateID{ get; set; }
}
However, the correct way to do this is still and issue. There has been one suggestion to use CacheAttached but I haven't been able to make that work, either.
Is Cache Attached actually required or am I missing something from including linked entities?
The intention is to search for a specific Inventory Item and get the Items and and Alternate ID(s) they have, meaning an Item may appear more than once in the Global Search. I have also made sure to reset IIS and rebuild full text indexes in case this was the issue.
I was writing a routine that required several fields from the InventoryItem DAC and I noticed all the attributes on the NoteID field. I know the [PXNote] attribute carries all the properties for the note field and methods, but what does the [PXSearchable] attribute do?
#region NoteID
public abstract class noteID : PX.Data.IBqlField { }
protected Guid? _NoteID;
[PXSearchable(SearchCategory.IN, "{0}: {1}",
new Type[] { typeof(InventoryItem.itemType), typeof(InventoryItem.inventoryCD) },
new Type[] { typeof(InventoryItem.descr) },
NumberFields = new Type[] { typeof(InventoryItem.inventoryCD) },
Line1Format = "{0}{1}{2}",
Line1Fields = new Type[] { typeof(INItemClass.itemClassCD),
typeof(INItemClass.descr),
typeof(InventoryItem.baseUnit) },
Line2Format = "{0}",
Line2Fields = new Type[] { typeof(InventoryItem.descr) },
WhereConstraint = typeof(Where<Current<InventoryItem.itemStatus>,
NotEqual<InventoryItemStatus.unknown>>)
)]
[PXNote]
public virtual Guid? NoteID { get; set; }
#endregion
PXSearchableAttribute is used for including specified fields of the records in the Acumatica's Full-Text Entity Index. It allows you searching that fields values in the top-left search-box(Modern UI).
I have created a Name value pair field for Sales Order table and Search is giving error while using the field from Description field in selector
#region UsrLoader
public abstract class usrLoader : IBqlField { }
[PXDBString(128, IsUnicode = true)]
[PXUIField(DisplayName = "Operator 1")]
[PXSelector(typeof(EPEmployee.acctCD),
new Type[]
{
typeof(EPEmployee.acctCD),
typeof(EPEmployee.acctName)
},
DescriptionField = typeof(EPEmployee.acctName))]
public virtual string UsrLoader { get; set; }
#endregion
#region UsrUnLoader
[PXDBString(128)]
[PXUIField(DisplayName = "Operator 2")]
[PXSelector(typeof(EPEmployee.acctCD),
new Type[]
{
typeof(EPEmployee.acctCD),
typeof(EPEmployee.acctName)
},
DescriptionField = typeof(EPEmployee.acctName))]
public virtual string UsrUnLoader { get; set; }
public abstract class usrUnLoader : IBqlField { }
#endregion
I am getting the following error
Typically I see the Invalid column error when the customization hasn't been published to insert the field in the database table. Did you publish after adding the fields?
Also, the warnings might tell you to join in the parent table. Did you try doing a join to the EPEmployee table to use the description/name field in your GI?