Sunday, February 11, 2018

Add custom fields in email to print mgmt settings PrintMgmtPrintDestinationTokens

To add custom fields like the image below, get to the PrintMgmtPrintDestinationTokens class and make the following modifications


PrintMgmtPrintDestinationTokens classDeclaration - add the following code (in red) to ClassDeclaration
[SrsPrintDestinationTokensExtAttribute('PrintMgmt')]
class PrintMgmtPrintDestinationTokens extends SrsPrintDestinationTokens
{
    Common jour;
    PrintMgmtDocType docType;
    container validTokens;

    SysLookupMultiSelectCtrl printMgmtMultiSelect;
    FormStringControl printMgmtCtl;
    FormCheckBoxControl printMgmtCheckBox;

    // Custom token for line manager
    FormCheckBoxControl lineMgrCheckBox;
    #define.LineMgrToken('@LineMgr@')
    #define.LineMgrTokenName('LineMgr')
}

PrintMgmtPrintDestinationTokens.addUICtls - add the following code (in red) to
protected void addUICtls(FormGroupControl _group)
{
    .
    .
    .
    printMgmtCheckBox = _group.addControl(FormControlType::CheckBox, 'PrintMgmtPrintDestinationPrimary');
    printMgmtCheckBox.widthMode(FormWidth::ColumnWidth);
    printMgmtCheckBox.label(partyType == PrintMgmtPrintDestinationPartyType::Unknown ?
            "@SYS316632" :
            strFmt("@SYS4004929", partyType));

    if (partyType == PrintMgmtPrintDestinationPartyType::Worker)//the condition for the new field based on party type or could even be document type
    {
        lineMgrCheckBox = _group.addControl(FormControlType::CheckBox, 'PrintMgmtPrintDestinationLineMgr');
        lineMgrCheckBox.widthMode(FormWidth::ColumnWidth);
        lineMgrCheckBox.label(strFmt("@SYS4004929", "@LABEL"));
    }
    .
    .
}


PrintMgmtPrintDestinationTokens.expandEmailToken- add the following code (in red) to expandEmailToken (screenshot here to keep things clear)

As you can see, a new method getHCMWorkerLineMgrEmail is defined here, this will let print mgmt settings know which email address to pick, so lets define that
protected str getHcmWorkerLineMgrEmail(Common _jour)
{
    PrintMgmtPrintDestinationPartyType  partyType;
    CustVendAC                          ac;
    str                                 addresses;
    HcmWorker                           hcmWorker, hcmWorkerMgr;
    HcmPositionRecId                    workerPositionRecId;

    [partyType, ac] = docType.getDestinationPartyTypeAndIdExt(_jour);//to get the party type in this class
    if (partyType == PrintMgmtPrintDestinationPartyType::Worker)
    {
        hcmWorker = HcmWorker::findByPersonnelNumber(ac);//to get the personnel number ac is defined above
        if (hcmWorker)
        {
            // Get worker's line manager
            workerPositionRecId = HcmWorker::getPrimaryPosition(hcmWorker.RecId);

            hcmWorkerMgr = ConcurExpWorkerFileWriter::findWorkerLineManager(workerPositionRecId);
            if (hcmWorkerMgr)
            {
                addresses = this.getEmailAddressForParty(partyType, hcmWorkerMgr.Person, '');
            }
        }
    }

    return addresses;
}
PrintMgmtPrintDestinationTokens.getUIAddresses- add the following code (in red)
public str getUIAddresses()
{
    str addresses = this.makeAddressTokens(printMgmtCtl.text());

    if(printMgmtCheckBox.checked())
    {
        addresses = this.appendAddresses(addresses, this.emptyToken());
    }

    if (lineMgrCheckBox)
    {
        if(lineMgrCheckBox.checked())
        {
            addresses = this.appendAddresses(addresses, #LineMgrToken);
        }
    }

    return this.appendAddresses(addresses, nextTokens ? nextTokens.getUIAddresses() : '');
}

Override the PrintMgmtPrintDestinationTokens.parseAddress as that is picked up from the parent class SrsPrintDestinationTokens and make sure it accommodates for our new tokens. This was completely non intuitive and most things had to be specified only here which do not exist in the parent class.
// Parse custom line manager token, to split from standard otherAddress (3rd element) to customToken (4rd element)
protected container parseAddresses(str _addresses, container _availableTokens)
{
    container       availableAddresses;
    str             otherAddresses;
    List            otherAddressesTokens;
    ListEnumerator  listEnum;
    List            customTokenList = new List(Types::String);
    List            otherAddressesList = new List(Types::String);
    str             sep = this.parmAddressSeparator();

    availableAddresses = super(_addresses, _availableTokens);

    otherAddresses = conPeek(availableAddresses, 3);
    otherAddressesTokens = strSplit(otherAddresses, this.parmAddressSeparator());
    listEnum = otherAddressesTokens.getEnumerator();

    while (listEnum.moveNext())
    {
        if (listEnum.current() == #LineMgrToken)
        {
            customTokenList.addEnd(listEnum.current());
        }
        else
        {
            otherAddressesList.addEnd(listEnum.current());
        }
    }

    return [conPeek(availableAddresses, 1), conPeek(availableAddresses, 2), SrsPrintDestinationTokens::list2Str(otherAddressesList, sep), SrsPrintDestinationTokens::list2Str(customTokenList, sep)];
}

The last method you need to modify is setUIAddresses. Just added the lines in red in the method
protected void setUIAddresses(str _addresses)
{
    container availableAddresses = this.parseAddresses(_addresses, conPeek(validTokens, 2));

    // We handle @token@ and @@ so pass the rest to super for further processing
    if(nextTokens)
    {
        nextTokens.setUIAddresses(conPeek(availableAddresses, 3));
    }

    printMgmtMultiSelect.set(this.selectTokens(conPeek(availableAddresses, 1), validTokens));
    printMgmtCtl.text(conPeek(availableAddresses, 1));
    printMgmtCheckBox.value(conPeek(availableAddresses, 2) != '');

    if (lineMgrCheckBox)
    {
        lineMgrCheckBox.value(conPeek(availableAddresses, 4) != '');
    }
}

These are the only changes I made to display the businesslineMgr in the window and picking up the manager's email whenever an email is sent to a subordinate.

So, the following methods were modified (and added) to make it work. I am also attaching the whole file here for easy reference.






Finding print destination email tokens

I had a requirement to look for print mgmt tokens for email to and log it. The following statement lets you do that

PrintMgmtSettings  printMgmtSettings;
    PrintMgmtReportFormat printMgmtReportFormat;
    PrintMgmtDocInstance printMgmtDocInstance;
   

 while select printMgmtSettings
    exists join printMgmtReportFormat
            where printMgmtReportFormat.Name==ssrsReportStr(ReportFORWHICHTHE PRINTMGMTSETTINGSAREDEFINED)
               && printMgmtReportFormat.RecId == printMgmtSettings.ReportFormat
    exists join printMgmtDocInstance
            where printMgmtDocInstance.DocumentType==PrintMgmtDocumentType::CORRECTNODETYPE
               && printMgmtDocInstance.PrintType==PrintMgmtDocInstanceType::Original
               && printMgmtDocInstance.RecId == printMgmtSettings.ParentId
    {
        srsPrintDestinationSettings = new srsPrintDestinationSettings(printMgmtSettings.PrintJobSettings);
        info(srsPrintDestinationSettings.emailTo());      //this prints@HOME@ and @PVTContact@ 
    }


Finding Conditions defined for print mgmt using X++

I had a requirement where I needed to look for print management conditions and then log it.

    PrintMgmtNodeInstance PrintMgmtNodeInstance;
    PrintMgmtSetupDoc PrintMgmtSetupDoc;
    PAECommunications PAECommunications;
    Query             query;
    int i;

 PrintMgmtNodeInstance = new PrintMgmtNodeInstance();
    PrintMgmtNodeInstance.parmNodeDefinition(new PrintMgmtNode_HRM());//or whatever your node is, sales/HCMWorker/depending on your situation this can vary.

    PrintMgmtNodeInstance.parmReferencedTableBuffer(tableBufferForPrintMGMTQuery);

    PrintMgmtSetupDoc = PrintMgmtSetupDoc::construct(PrintMgmtNodeInstance, PrintMgmtDocumentType::YOURPRINTMGMTDocType, CompanyInfo::languageId());
 
 i= PrintMgmtSetupDoc.getInstanceByPos(1).numConditionalSettings(); //the instance is always 1 so this is safe
   
    for (i=1;i<PrintMgmtSetupDoc.getInstanceByPos(1).numConditionalSettings();i++)
    {
        query = PrintMgmtSetupDoc.getInstanceByPos(1).getConditionalSettingByPos(1).parmCondition();//this gives the query
    }

So, the above code for a setup like below gives me the query defined in both conditions