Required of BQL in FBQL of Acumatica

Hello everybody,

today I want to describe how analogue to Required works in Acumatica Framework.

For example, in the past ( before 2019 R1 ) you may read something from Acumatica with help of Required:

var contact = PXSelect<ContactWhere<Contact.displayNameIsNotNullAnd<Contact.displayName
Contains<Required<Contact.displayName>>>>>.SelectWindowed(graph, startIdx, 1, ' ').First();

Now, you can use @P.AsString, as shown on code sample below:

var contact = SelectFrom<Contact>.Where<Contact.displayName.IsNotNull.And<Contact.displayName.
Contains<@P.AsString>>>.View.SelectWindowed(graph, startIdx, 1, ' ').First();

Conclusion

Also take a note, that FBQL looks a bit simpler then BQL which has plenty of <<<>>>>

Acumatica developers conference 2018 part 1

Hello everybody,

I want to summarize what I've seen and heard at latest Acumatica Developers conference.

First of all, I'd like to say that idea from Gabriel Michaud about using of attributes that can save plenty of time during development.

Part 1

Everyday trips and tricks (Magic attributes and BQL operands)

Lets start. For examle how to make a field required (or visible, or enabled) dynamically:

Traditional way (old version):

protected virtual void SOOrder_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
{
    SOOrder doc = e.Row as SOOrder;
    if (doc == null)
    {
           return;
    }

    if (doc.OrderType == "SO")
    {
          PXDefaultAttribute.SetPersistingCheck<SOOrder.customerOrderNbr>(cache, doc, PXPersistingCheck.NullOrBlank);
    }
    else
    {
        PXDefaultAttribute.SetPersistingCheck<SOOrder.customerOrderNbr>(cache, doc, PXPersistingCheck.Nothing);
    }
}

New way, using PXUIRequired attribute:

[PXMergeAttributes(Method = MergeMethod.Append)]
[PXDefault]
[PXUIRequired(typeof(Where<SOOrder.orderTypeEqual<sOOrderType>>))]
public string CustomerOrderNbr { getset; }

So now if you try to create Sales Order with Order Type "SO" and no enter Customer Order Acumatica show "Erorr, Customer Order Cannot be Empty"

 

Another attribute it is PXUIVisible:

[PXMergeAttributes(Method = MergeMethod.Append)]
[PXUIVisible(typeof(Where<Selector<SOOrder.customerIDCustomer.customerClassID>, Equal<keyCustomersClass>>))]
public string ProjectID { getset; }

So using this PXUIVisible we can make field visible or no; Also pat attention that Selector<> is powerfull and fast operand, becouse it get data from memory (cache);

 

Another attribute it is PXUIVerify:

[PXMergeAttributes(Method = MergeMethod.Append)]
[PXUIVerify(typeof(Where<SOOrder.requestDateGreater<SOOrder.orderDate>>), PXErrorLevel.Warning, "Request date should be greater than order date")]
public DateTime? RequestDate { getset; }

Use this way we can verify field. If we set PXErrorLevel.Erorr we can`t save data (if it is need);

 

Another attribute it is PXUIEnabled + PXDefault + PXFormula trigger:

[PXMergeAttributes(Method = MergeMethod.Append)]
[PXUIEnabled(typeof(Where<Selector<SOOrder.projectIDPMProject.nonProject>, Equal<True>>))]
[PXDefault(typeof(Search<PMTask.descriptionWhere<PMTask.projectIDEqual<Current<SOOrder.projectID>>>>),PersistingCheck = PXPersistingCheck.Nothing)]
[PXFormula(typeof(Default<SOOrder.projectID>))]
public  string OrderDesc { getset; }

Here Order description defaulted from Project and only editable for "X" (non-project);

PXFormula for force update of default value when ProjectID changes - replaces SetDefault;

 

Another attribute it is PXFormula + Selector:

[PXDBPriceCost]
[PXUIField(DisplayName = "MSRP", Enabled = false)]
[PXFormula(typeof(Selector<SOLine.inventoryIDInventoryItem.recPrice>))]
public decimal? UsrRecPrice { getset; }

Here I add new UsrRecPrice, and use Selector, this field will be refresh price when I will change inventoryId;

 

So use this attributes in yours projects;

Required instead of current in Acumatica

Hello everybody,

today I want to fulfill my promise that I gave to one of my readers. 

He left at mine blog following question:

How do we use required<> in place of current<> and pass some string constant for selector? That question was asked in context of this article. 

That is good question and I also want to add that answer on it will be at least to some degree disappointing. First of all, if you work with selectors, you can't use Required. Required is intended for use in Graphs.

But if you want to use some constant filtering conditions, you don't need Required attribute at all. You can use mechanism of Constants, which works perfectly without Required. 

Take a look at the following declaration:

public static class OrderTypes
{
    public const string N = "N";
    public const string C = "C";
 
    public class closed : Constant<String>
    {
        public closed()
            : base(C)
        {
        }
    }
 
    public class open : Constant<String>
    {
        public open() : base(N)
        {
        }
    }
}

As you can see, we declared two cosntants for order types: N and C.

Below goes code that shows how can you create selector that will filter Orders by OrderTypes with usage of those constants:

 

class Test : PXCacheExtension<SOOrder>
{
    #region UsrPreviousTermsId
 
    public abstract class usrPreviousTermsId : IBqlField
    {
    }
 
    [PXSelector(typeof(Search<SOOrder.orderNbrWhere<SOOrder.statusEqual<OrderTypes.closed>>>))]
    [PXUIField(DisplayName = "Linked sales order")]
    [PXDBString(10, IsUnicode = true)]
    public string UsrLinkedSalesOrder { getset; }
 
    #endregion
}

Such code will give you selector that give you a list of orders with status closed. Also this sample of code shows that for selector you don't need Required in order to filter by some constant value.

 

Make PXDefault as not required for input

Hello everybody,

Imagine following situation, you added to your DAC field some default value. For example like this:

[PXDBDate]
[PXDefault(typeof(AccessInfo.businessDate))]
public virtual DateTime? FromDate

And now you have default value as current date. But what, if you don't like to make it required for input. How to achieve this goal? The answer is quite simple, you just need to add PersistingCheck = PXPersistingCheck.Nothing into pxdefault attribute. Like this:

[PXDBDate]
[PXDefault(typeof(AccessInfo.businessDate), PersistingCheck = PXPersistingCheck.Nothing)]
public virtual DateTime? FromDate

With such changes you can init your values at form, and make it not required for input