简体   繁体   中英

Check if a vendor has any transactions across ALL companies in the past X days in Dynamics AX

I am trying to write a report that at first glance seemed fairly straightforward. However, after numerous attempts, I am struggling to find an approach that works. We have about 350K records in VendTable, but vendors are duplicated across 26 companies so in reality there ~13K UNIQUE vendor accounts.

I am trying to write a report that returns any vendor that has not had a PO, Invoice and Payment (PurchTable, VendInvoiceJour and VendTable respectively) since a certain date.

The complex part (for me) is, all the keys contain dataareaid, but I want my query to run independently of that. I don't mean crossCompany, because that would return (up to) 26 records for a single Vendor (since it exists 26 times in the database). To be clear, if vendor A has a PO in ANY company, I don't want vendor A returned in my resultset AT ALL.

I have tried doing this using the query below (the +'' on the AccountNum tricks the AOT so the resulting sql query drops dataareaid from the subquery) but the resulting SQL was NESTED "NOT (EXIST" so the NOTs cancel out causing unexpected and incorrect results.

X++ Code

while select crossCompany AccountNum, InvoiceAccount, NBDCMMSAllowInvoices, VendGroup, Party
    from vendTable
    group by AccountNum, InvoiceAccount, Party, VendGroup, NBDCMMSAllowInvoices
    where vendTable.Blocked != CustVendorBlocked::All
        notExists join * from purchTable WHERE
                purchTable.OrderAccount == vendTable.AccountNum+''
             && purchTable.createdDateTime > cutoffDate
        notExists join * from vendTrans
        where vendTrans.AccountNum == vendTable.accountNum+''
             && vendTrans.TransDate > cutoffDateTrans
        notExists join * from vendInvoiceJour
        where vendInvoiceJour.InvoiceAccount == vendTable.accountNum+''
             && vendInvoiceJour.InvoiceDate > cutoffDateTrans

Resulting SQL:

SELECT T1.ACCOUNTNUM,T1.INVOICEACCOUNT,T1.NBDCMMSALLOWINVOICES,T1.VENDGROUP,T1.PARTY,T1.DATAAREAID,T1.RECID 
FROM VENDTABLE T1 WHERE ((T1.PARTITION = PartitionID) AND (T1.BLOCKED <> 2)) 
AND NOT (EXISTS (SELECT 'x' FROM PURCHTABLE T2 WHERE 
                ((T2.PARTITION = PartitionID) AND     ((T2.ORDERACCOUNT=T1.ACCOUNTNUM AND (T2.DATAAREAID = T1.DATAAREAID) AND     (T2.PARTITION = T1.PARTITION)) AND (T2.CREATEDDATETIME>?))) 
                AND NOT (EXISTS (SELECT 'x' FROM VENDTRANS T3 WHERE 
                                ((T3.PARTITION = PartitionID) AND ((T3.ACCOUNTNUM=T1.ACCOUNTNUM AND (T3.DATAAREAID = T1.DATAAREAID) AND (T3.PARTITION = T1.PARTITION)) AND (T3.TRANSDATE>?)))
                                AND NOT (EXISTS (SELECT 'x' FROM VENDINVOICEJOUR T4 WHERE 
                                                ((T4.PARTITION = PartitionID) AND ((T4.INVOICEACCOUNT=T1.ACCOUNTNUM AND (T4.DATAAREAID = T1.DATAAREAID) AND (T4.PARTITION = T1.PARTITION)) AND (T4.INVOICEDATE>?)))
                                                )
                                        )
                                )
                        )
                )
        ) GROUP BY T1.ACCOUNTNUM,T1.INVOICEACCOUNT,T1.NBDCMMSALLOWINVOICES,T1.VENDGROUP,T1.PARTY ORDER BY T1.ACCOUNTNUM,T1.INVOICEACCOUNT,T1.NBDCMMSALLOWINVOICES,T1.VENDGROUP,T1.PARTY

Those nested NOT EXIST join are causing me grief. Is there some way around this, or perhaps a completely different approach?

I suppose you can't use a query?

Query                   q;
QueryBuildDataSource    qbdsVendTable;
QueryBuildDataSource    qbds;
QueryRun                qr;

q = new Query();
q.allowCrossCompany(true);

qbdsVendTable = q.addDataSource(tableNum(VendTable));
qbdsVendTable.addSelectionField(fieldNum(VendTable, AccountNum));
qbdsVendTable.addSelectionField(fieldNum(VendTable, InvoiceAccount));
qbdsVendTable.addSelectionField(fieldNum(VendTable, NBDCMMSAllowInvoices));
qbdsVendTable.addSelectionField(fieldNum(VendTable, VendGroup));
qbdsVendTable.addSelectionField(fieldNum(VendTable, Party));
qbdsVendTable.addGroupByField(fieldNum(VendTable, AccountNum));
qbdsVendTable.addGroupByField(fieldNum(VendTable, InvoiceAccount));
qbdsVendTable.addGroupByField(fieldNum(VendTable, NBDCMMSAllowInvoices));
qbdsVendTable.addGroupByField(fieldNum(VendTable, VendGroup));
qbdsVendTable.addGroupByField(fieldNum(VendTable, Party));
qbdsVendTable.addRange(fieldNum(vendTable, Blocked)).value(SysQuery::valueNot(CustVendorBlocked::All));

qbds = qbdsVendTable.addDataSource(tableNum(PurchTable));
qbds.joinMode(JoinMode::NoExistsJoin);
qbds.addLink(fieldNum(VendTable, AccountNum), fieldNum(PurchTable, OrderAccount));
qbds.addRange(fieldNum(PurchTable, CreatedDateTime)).value('>'+queryValue(cutoffDate));

qbds = qbdsVendTable.addDataSource(tableNum(VendTrans));
qbds.joinMode(JoinMode::NoExistsJoin);
qbds.addLink(fieldNum(VendTable, AccountNum), fieldNum(VendTrans, AccountNum));
qbds.addRange(fieldNum(VendTrans, TransDate)).value('>'+queryValue(cutoffDateTrans));

qbds = qbdsVendTable.addDataSource(tableNum(VendInvoiceJour));
qbds.joinMode(JoinMode::NoExistsJoin);
qbds.addLink(fieldNum(VendTable, AccountNum), fieldNum(VendInvoiceJour, InvoiceAccount));
qbds.addRange(fieldNum(VendInvoiceJour, InvoiceDate)).value('>'+queryValue(cutoffDateTrans));

qr = new QueryRun(q);

while (qr.next())
{
    vendTable = qr.get(tableNum(vendTable));

    //and so on
}

If not then just create a view based on a union query and use it in your report. You can use VendTable as a parent datasource, ie VendTable join PurchTable, VendTable join VendTrans, and VendTable join VendInvoiceJour in a union, or decide to use a different union structure eg no VendTable and only specific fields from the other 3 tables. You can use computed columns if necessary. Then just select records from VendTable notExists join your new view.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM