Skip to main content

I’m still new to programming in Acumatica, so I may have gotten several things wrong here, but I’m trying to get a single value to be returned from this BQL statement which should be the sum of a specific customer’s invoices for the current year for the price of goods only. I’m getting a highlighted error in Visual Studio that says that the entire BQL statement is a type that is not valid in the given context. I’m also not sure if the Convert.ToDecimal function will work with an ARInvoice.curyGoodsTotal object.

 

namespace PX.Objects.AR
{
public class DateYearStart : PX.Data.BQL.BqlDateTime.Constant<DateYearStart>
{
public DateYearStart()
: base(new DateTime(DateTime.Today.Year, 1, 1))
{
}
}

public class DocTypeString : PX.Data.BQL.BqlString.Constant<DocTypeString>
{
public DocTypeString()
: base("INV")
{
}
}

public class CustomerMaint_Extension : PXGraphExtension<PX.Objects.AR.CustomerMaint>
{
protected virtual void YTD_Invoiced_Total_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e)
{
if (e.Row == null) return;

BAccount account = (BAccount)e.Row;
BAccountExt accountExt = sender.GetExtension<BAccountExt>(account);

if (accountExt != null)
{
List<ARInvoice.curyGoodsTotal> curyGoodsList = SelectFrom<ARInvoice>
.LeftJoin<ARRegister>
.On<ARInvoice.refNbr.IsEqual<ARRegister.refNbr>>
.Where<
Brackets<ARInvoice.docType.IsEqual<Use<DocTypeString>.AsString>.
And<ARRegister.customerID.IsEqual<Use<Current<Customer.bAccountID>>.AsInt>>.
And<ARRegister.docDate.IsLessEqual<Use<Today>.AsDateTime>>.
And<ARRegister.docDate.IsGreaterEqual<Use<DateYearStart>.AsDateTime>>>>.
AggregateTo<Sum<ARInvoice.curyGoodsTotal>>;

accountExt.UsrYTDInvTotal = Convert.ToDecimal(curyGoodsListu0]);
}
}
}
}

 

Hi @tararosenthal 

There are a few issues and optimizations to make in your code:

  1. Invalid use of BQL: The main issue is how you've constructed your BQL statement and how you're using it. BQL is not executed directly but rather prepares a SQL statement which is then executed on the database. You don't run the BQL query directly; instead, you should use it in conjunction with graph or view operations to fetch the data.

  2. Incorrect use of .AsString and .AsInt: You should use .Value to fetch constant values for comparisons.

  3. Using List for the result: The BQL will return a list of PXResult objects, not a list of decimals.

  4. Use of FieldUpdated event: This event might not be the best event to use for your purposes, especially if you only want to run the query under certain conditions. For simplicity, we'll keep it for this example.

Here's a corrected version:

 

namespace PX.Objects.AR
{
public class DateYearStart : PX.Data.BQL.BqlDateTime.Constant<DateYearStart>
{
public DateYearStart()
: base(new DateTime(DateTime.Today.Year, 1, 1))
{
}
}

public class DocTypeString : PX.Data.BQL.BqlString.Constant<DocTypeString>
{
public DocTypeString()
: base("INV")
{
}
}

public class CustomerMaint_Extension : PXGraphExtension<PX.Objects.AR.CustomerMaint>
{
protected virtual void BAccount_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e)
{
if (e.Row == null) return;

BAccount account = (BAccount)e.Row;
BAccountExt accountExt = sender.GetExtension<BAccountExt>(account);

if (accountExt != null)
{
PXResultset<ARInvoice> curyGoodsResults = PXSelectGroupBy<ARInvoice,
Where<ARInvoice.docType, Equal<DocTypeString>,
And<ARInvoice.customerID, Equal<Current<Customer.bAccountID>>,
And<ARInvoice.docDate, LessEqual<Today>,
And<ARInvoice.docDate, GreaterEqual<DateYearStart>>>>>,
Aggregate<Sum<ARInvoice.curyGoodsTotal>>>.Select(Base);

if(curyGoodsResults != null && curyGoodsResults.Count > 0)
{
ARInvoice aggregatedInvoice = curyGoodsResults.First();
accountExt.UsrYTDInvTotal = aggregatedInvoice.CuryGoodsTotal ?? 0m;
}
else
{
accountExt.UsrYTDInvTotal = 0m;
}
}
}
}
}

A few things to remember:

  1. BQL returns a PXResultset of the main DAC being selected. So if you're selecting from ARInvoice, you'll get a PXResultset of ARInvoice.
  2. Aggregates like Sum in BQL will only return one record in the result set that contains the aggregated value.
  3. BQL constants are fetched using the .Value property.
  4. Always check for null values before using them.
  5. Ensure the logic is being triggered at the correct time and under the right conditions. The FieldUpdated event may not be the best event for all scenarios.

Hello @davidnavasardyan09, thank you so much for your detailed reply. It was really helpful. I changed the action to FieldSelecting, which I’m not sure if that’s the best either, but it worked for me. I also changed it so that the value is not saved in the database but just calculated each time. Again, probably not super efficient, but I wasn’t able to get it to work otherwise. I’m not sure why, but it wasn’t saving the value in the database even though I could see from the stack trace that it was being calculated correctly, so I just returned the value instead. Thanks again for your help.


Reply