Using SubstituteKey with Joined Table - acumatica

I have a selector defined in this manner:
[PXSelector(typeof(Search2<TableA.id, LeftJoin<TableB, On<TableB.refNbr, Equal<TableA.refNbr>>>,
Where<TableA.woid, IsNull, And<TableB.tranType, Equal<TranType>, And<TableB.lotSerialNbr, NotEqual<StringEmpty>>>>>),
typeof(TableA.id), typeof(TableB.lotSerialNbr), SubstituteKey = typeof(TableB.lotSerialNbr))]
However the selector does not show the SubstituteKey value. Am I able to assign the SubsistiteKey belonging to a joined table instead of the original table and show/fetch its value?

It's not supported to assign the SubsistiteKey to a joined table field. As an alternative, let me suggest to declare an unbound field in TableA and decorate it with the PXDBScalarAttribute to calculate its value on database level:
[PXDBScalar(typeof(Search<TableB.lotSerialNbr, <TableB.refNbr, Equal<TableA.refNbr>>>))]

Related

Extend Generic Inquiry to Show the Number of records

Is it possible to extend the Generic Inquiry screen so that it shows the number of records retrieved? Or perhaps is it possible to use PXGenericInqGrph to get the number of records of a Generic Inquiry?
However, it is important, for performance reasons that I only retrieve one record with the total from the Database. and not getting all records from the database and doing a Count at the Application layer.
At least up until Acumatica 7.207.0029 there is no method to extend the Generic Inquiry results screen.
If you only need the record count, what you can do is edit your GI or create a copy to get the total and use the special <Count> field to get the record count.
Of course this requires you to set a GroupBy field and you need this to be the same for all records if you want a total record count.
If your query has a field you know to be equal to all records, you can use that field in the GroupBy tab. If not, there is a way to do this by adding a join to an number table.
Number Table Workaround
This technique uses a table with numbers to create specific queries. In this case we can join it to your query to add a known common value to all rows.
Here is the XML for a Customization Project that creates this table and makes it available as the Is.Objects.Core.ISNumbers DAC.
<Customization level="200" description="Number utility table" product-version="17.207">
<Graph ClassName="ISNumbers" Source="#CDATA" IsNew="True" FileType="NewDac">
<CDATA name="Source"><![CDATA[using System;
using PX.Data;
namespace IS.Objects.Core
{
[Serializable]
public class ISNumbers: IBqlTable
{
#region Number
[PXDBInt(IsKey = true)]
[PXUIField(DisplayName = "Number", IsReadOnly = true)]
public int? Number { get; set; }
public class number : IBqlField{}
#endregion
}
}]]></CDATA>
</Graph>
<Sql TableName="ISNumbers" CustomScript="#CDATA">
<CDATA name="CustomScript"><![CDATA[IF OBJECT_ID('ISNumbers', 'U') IS NOT NULL DROP TABLE ISNumbers;
SELECT TOP 10000 IDENTITY(int,1,1) AS Number
INTO ISNumbers
FROM sys.objects s1
CROSS JOIN sys.objects s2
ALTER TABLE ISNumbers ADD CONSTRAINT PK_ISNumbers PRIMARY KEY CLUSTERED (Number)]]></CDATA>
</Sql>
</Customization>
Just add the table to the GI and crate an INNER JOIN relation where the value of the number field equals 1:
Then you can use this field in the GroupBy condition.
Then you can add the Numbers field and set its value to <Count>. Leave all your other result fields to keep the logic but hide them if you don't need them (they will be automatically grouped by max value).
All queries performed by GIs are executed in the DB so you don't need to worry about it running in the App side.

How to aggregate a field in BQL for complex query

I have a BQL query joining three tables as follows:
foreach (PXResult<GLTran, Branch, xTACOpenSourceDetail> rec in
PXSelectJoin<GLTran,
InnerJoin<Branch,
On<GLTran.branchID, Equal<Branch.branchID>>,
InnerJoin<xTACOpenSourceDetail,
On<Branch.branchCD, Equal<xTACOpenSourceDetail.string03>,
And<xTACOpenSourceDetail.openSourceName, Equal<Constants.openSourceName>,
And<xTACOpenSourceDetail.dataID, Equal<Constants.privateer>>>>>>,
Where<Branch.branchCD, NotEqual<Required<Branch.branchCD>>,
And<GLTran.posted, Equal<True>,
And<GLTran.ledgerID, Equal<Required<GLTran.ledgerID>>,
And<GLTran.tranDate, GreaterEqual<Required<GLTran.tranDate>>>>>>,
OrderBy<Asc<xTACOpenSourceDetail.string01, Asc<GLTran.batchNbr>>>>.Select(Base, osdBranch.String03, ledger.LedgerID, tacsmlm.Date01))
I want to add one aggregated field, namely the sum of the GLTran.CuryDebitAmt grouped by GLTran.BatNbr and Branch.BranchCD.
I can easily do this in SQL using the SUM OVER functionality as follows:
SELECT SUM(GLTran.CuryDebitAmt) OVER (PARTITION BY GLTran.BatchNbr, Branch.BranchCD) as 'BatchTotal'
,GLTran.*
,Branch.*
,xTACOpenSourceDetail.*
FROM GLTran
Inner Join Branch
On GLTran.branchID = Branch.branchID
AND Branch.CompanyID = GLTran.CompanyID
Inner Join xTACOpenSourceDetail
On Branch.branchCD = xTACOpenSourceDetail.string03
And xTACOpenSourceDetail.openSourceName = 'TAC FM Map Company Branch'
And xTACOpenSourceDetail.dataID = 'Privateer'
AND xTACOpenSourceDetail.CompanyID = GLTran.CompanyID
Where Branch.branchCD <> '000 0000'
And GLTran.posted = 1
And GLTran.ledgerID = 6
And GLTran.tranDate >= '08/03/2017'
AND GLTran.CompanyID = 2
Order
By xTACOpenSourceDetail.string01 ASC
,GLTran.batchNbr ASC
...but I have no idea how to add this single summed field in BQL. Any help is appreciated.
You will use a PXSelectGroupBy and in your Aggreate for the BQL indicate which fields will "SUM" their values. Any field not called out will be the MAX value.
If you search SUM< in the Acumatica source you can find plenty of BQL examples. Here is a BQL Example from ARPaymentEntry. Only two (curyAdjdAmt & adjAmt) fields will contain a SUM while all other fields returned will be the MAX.
SOAdjust other = PXSelectGroupBy<SOAdjust,
Where<SOAdjust.voided, Equal<False>,
And<SOAdjust.adjdOrderType, Equal<Required<SOAdjust.adjdOrderType>>,
And<SOAdjust.adjdOrderNbr, Equal<Required<SOAdjust.adjdOrderNbr>>,
And<
Where<SOAdjust.adjgDocType, NotEqual<Required<SOAdjust.adjgDocType>>,
Or<SOAdjust.adjgRefNbr, NotEqual<Required<SOAdjust.adjgRefNbr>>>>>>>>,
Aggregate<GroupBy<SOAdjust.adjdOrderType,
GroupBy<SOAdjust.adjdOrderNbr,
Sum<SOAdjust.curyAdjdAmt,
Sum<SOAdjust.adjAmt>>>>>>.Select(this, adj.AdjdOrderType, adj.AdjdOrderNbr, adj.AdjgDocType, adj.AdjgRefNbr);
Another alternative solution for your question would be to create a PXProjection which could be the sum by group values which you then in your regular select include the projection table vs the base table in your BQL. I don't know the performance benefits vs one or the other - just another option.

Cassandra: Inserting column in cassandra table

I am trying to insert new column in Cassandra table.
Column Name- feedback_map
Column type- map of text, feedback_map
And trying to execute this statement.
ALTER TABLE my_table ADD feedback_map map<text, frozen<feedback_details>>;
but getting unknown type error on feedback_details
Am pretty new to cassandra.
I am having custom feedback_details user type with two field-
#Field(name = "field_mappings")
private Map<String, String> fieldMappings;
#Field(name = "field_defaults")
private Map<String, String> fieldDefaults;
No i have not defined it yet? do i need to add this user type to my table first??
First, make sure that your User Defined Type (UDT) exists. If not, you'll need to create it:
CREATE TYPE feedback_details (
field_mappings MAP<TEXT, TEXT>,
field_defaults MAP<TEXT, TEXT>);
Then you'll be able to add it as a column on your table (as you have above):
ALTER TABLE my_table ADD feedback_map map<text, frozen<feedback_details>>;

subsonic 2.2 does not update nullable columns to null values

When using the Update method on ODSController (ie using GridView / FormView in an ASP.NET application) and passing null values to nullable columns, the nullable column value remains unchanged.
This is due to the way that update method instantiate the ActiveRecord to update:
public void Update(Guid MyKey, ...)
{
MyItem item = new MyItem();
item.MarkOld();
item.IsLoaded = true;
...
item.Save(UserName);
}
By creating an empty MyItem instance (all fields are null) and setting a nullable field to null doesn' t allow the column to finish in the DirtyColumns collection (see ActiveHelper GetUpdateCommand).
Am I going to have write custom update functions for EVERY table in my database to resolve this?

Querying multiple tables with a where clause in LINQ to SQL

Forgive my ignorance with Linq to SQL but...
How do you query mulitple tables in one fell swoop?
Example:
I want to query, say 4 tables for a title that includes the following word "penguin". Funnily enough each table also has a field called TITLE.
Tables are like so:
I want to query each table (column: TITLE) for the word "penguin". Each table is referenced (via foreign key) to a parent table that is simply called Reference, and is linked on a column called REF_ID. So ideally the result should come back with a list of REF_ID's where the query criteria was matched.
If you can help you will be richly rewarded....... (with a green tick ;)
The code I have works for just one table - but not for two:
var refs = db.REFERENCEs
.Include(r => r.BOOK).Where(r => r.BOOK.TITLE.Contains(titleString)).Include(r => r.JOURNAL.AUTHORs)
.Include(r => r.JOURNAL).Where(r => r.JOURNAL.TITLE.Contains(titleString));
I had a similar scenario a while back and ended up creating a view that unioned my tables and then mapped that view to a LINQ-to-SQL entity.
Something like this:
create view dbo.References as
select ref_id, title, 'Book' as source from dbo.Book
union all
select ref_id, title, 'Journal' from dbo.Journal
union all
select ref_id, title, 'Magazine' from dbo.Magazine
union all
select ref_id, title, 'Report' from dbo.Report
The mapping would look like this (using attributes):
[Table(Name="References")]
public class Reference {
[Column(Name="Ref_Id", IsPrimaryKey=true)]
public int Id {get;set;}
[Column]
public string Title {get;set;}
[Column]
public string Source {get;set;}
}
Then a query might look like this:
var query = db.GetTable<Reference>().Where(r => r.Title.Contains(titleString));

Resources