Tuesday, October 12, 2021

Purchase order print outs to respective person automatically by email X++

Hi folks,

This blog will be useful for customizing requirements that are related to sending document prints (Purchase order, Sales Invoice etc) internal or external via email.

Requirement:

I got the requirement where in Procurement team wanted to send PO print outs to the buyers automatically through emails as soon as POs are confirmed. Since, PO was created from RFQ as a part of process and RFQ had a reference of buyers so buyer worker ID reference from RFQ was being used in order to get buyer email address on which PO print out email had to be sent.

Solution: 

To automate PO print out via email, there must be trigger point on which email has to be sent. PO print out is generated at the time of confirming the POs therefore this trigger point of PO confirmation is being used to sent out emails to the buyers. Since, same PO can have multiple confirmation versions so to avoid sending same PO confirmation version to the buyers, there is a flag added on the PO confirmation version table that identifies whether PO confirmation version had been sent to the buyer or not. If PO is not yet sent to the buyer then flag will be No and system will send that PO to the buyer otherwise PO will not be sent to the buyer in case of flag set as Yes.

Create a class which is extended from batch class that is used to process the events or actions periodically. In this case email sending to the buyers is the periodic event that occurs every time when PO is confirmed.

//This class is used to process the email action periodically using batch framework class

class POConfirmationAttachmentsToBuyer extends RunBaseBatch

{

    public void run()
    {
        VendPurchOrderJour          vendPurchOrderJour;
        PurchTable                         purchTable;
           
        super();

        while select firstonly vendPurchOrderJour
        order by RecId desc
        join  purchTable
        where purchTable.PurchId == vendPurchOrderJour.PurchId
        &&    vendPurchOrderJour.IsEmailSent == NoYes::No 
        {
                this.runAndSaveSSRSReport(vendPurchOrderJour);
        }
    }

    public void runAndSaveSSRSReport(vendPurchOrderJour _vendPurchOrderJour)
    {
        PurchReqLine                                                  purchreqline;
        PURCHRFQCASETABLE                             purchRFQCaseTable;
        PurchLine                                                        purchLine; 
        container                                                          binData;
        Binary                                                              binaryData;
          
        try
       {
            select  firstonly PurchReqLineRefId from  purchLine
            where purchLine.PurchId                          == _vendPurchOrderJour.PurchId;
            join     purchreqline
            where purchreqline.LineRefId                   == purchLine.PurchReqLineRefId;
            join     purchRFQCaseTable
            where PurchRFQCaseTable.RFQCaseId   == purchreqline.PURCHRFQCASEID;

            SrsReportRunController          controller = new SrsReportRunController();
            PurchPurchaseOrderContract      contract = new PurchPurchaseOrderContract();
            SRSPrintDestinationSettings     settings;
            Array                           arrayFiles;
            System.Byte[]                   reportBytes = new System.Byte[0]();
            SRSProxy                        srsProxy;
            SRSReportRunService             srsReportRunService = new SrsReportRunService();
            Microsoft.Dynamics.AX.Framework.Reporting.Shared.ReportingService.ParameterValue[] parameterValueArray;
           Map reportParametersMap;
           SRSReportExecutionInfo executionInfo = new SRSReportExecutionInfo();
           Args                                    args;
           args = new Args();
           controller.parmArgs(args);
           controller.parmReportName(ssrsReportStr(PurchPurchaseOrderExtCopy, Report));
           controller.parmShowDialog(false);
           controller.parmLoadFromSysLastValue(false);
           contract = controller.parmReportContract().parmRdpContract();
           contract.parmRecordId(_vendPurchOrderJour.RecId);
           settings = controller.parmReportContract().parmPrintSettings();
           settings.printMediumType(SRSPrintMediumType::File);
           settings.fileName(_vendPurchOrderJour.PurchId + "-" +                                                                    VendTable::find(_vendPurchOrderJour.OrderAccount).name());
           settings.fileFormat(SRSReportFileFormat::PDF);                                           controller.parmReportContract().parmReportServerConfig(SRSConfiguration::getDefaultServerConfiguration());
       controller.parmReportContract().parmReportExecutionInfo(executionInfo);
       srsReportRunService.getReportDataContract(controller.parmreportcontract().parmReportName());
       srsReportRunService.preRunReport(controller.parmreportcontract());
       reportParametersMap =                              srsReportRunService.createParamMapFromContract(controller.parmReportContract());
       parameterValueArray = SrsReportRunUtil::getParameterValueArray(reportParametersMap);
       srsProxy =                      SRSProxy::constructWithConfiguration(controller.parmReportContract().parmReportServerConfig());
            reportBytes =      srsproxy.renderReportToByteArray(controller.parmreportcontract().parmreportpath(),
                                                  parameterValueArray,
                                                  settings.fileFormat(),
                                                  settings.deviceinfo());            
            System.IO.MemoryStream mstream = new System.IO.MemoryStream(reportBytes);
            binaryData = Binary::constructFromMemoryStream(mstream);
            if(binaryData)
           {
                binData = binaryData.getContainer();
           }
            Map map=new Map (Types::String,Types::String);
            map.insert(strFmt("Dear %1,<o:p></o:p></p><p></p><p>Please find attached PO Print out.                 <o:p></o:p></p><p></p><p>Regards,<o:p></o:p></p><p></p><p><span style='font-                        size:12.0pt'> ERP Team<o:p></o:p></span>                    </p>",HcmWorker::find(PurchRFQCaseTable.Requester).name()), "message");
       
            POConfirmationEmailSentToBuyers::sendPDFEamilAttachment("PO", "en-                US",HcmWorker::find(PurchRFQCaseTable.Requester).email(), map, binData,             _vendPurchOrderJour.PurchId + "-" + VendTable::find(_vendPurchOrderJour.OrderAccount).name());

            ttsbegin;
            
            _vendPurchOrderJour.selectforupdate(true);
            
            _vendPurchOrderJour.IsEmailSent = NoYes::Yes;
            _vendPurchOrderJour.doUpdate();

            ttscommit;
        }
        catch(Exception::Error)
        {
            ttsbegin;

            _vendPurchOrderJour.selectforupdate(true);
        
            _vendPurchOrderJour.IsEmailSent = NoYes::No;
            _vendPurchOrderJour.doUpdate();

            ttscommit;
        }
    }
}

//This class is used to send emails to the Buyers
public static class POConfirmationEmailSentToBuyers
{
    public static void sendPDFEamilAttachment(SysEmailId      _emailId,
        LanguageId      _language,
        SysEmailAddress             _emailAddr,
        Map             _mappings,container _binData,str _fileName)
    {
        SysEmailItemId                   nextEmailItemId;
        SysEmailTable                    sysEmailTable;
        SysEmailMessageTable             sysEmailMessageTable;
        SysEmailContents                 sysEmailContents;
        SysOutgoingEmailTable            outgoingEmailTable;
        SysOutgoingEmailData             outgoingEmailData;
        Filename filename, FileExtension;
        Str1260  emailcontents, filNameSplit;
      
        FileExtension="";
       
        select sysEmailTable
               join    sysEmailMessageTable
                    where sysEmailMessageTable.EmailId== _emailId
                    && sysEmailMessageTable.LanguageId==_language;
       
        if(sysEmailTable.RecId>0)
        {
            emailcontents = POConfirmationEmailSentToBuyers::map2str(_mappings);
            sysEmailContents= emailcontents;
            
            nextEmailItemId = EventInbox::nextEventId();
      
            filename =strFmt("%1_%2.pdf",nextEmailItemId,_fileName);
    
            outgoingEmailTable.clear();
            outgoingEmailTable.Origin =sysEmailTable.Description;
            outgoingEmailTable.EmailItemId = nextEmailItemId;
            outgoingEmailTable.IsSystemEmail = NoYes::Yes;
            outgoingEmailTable.Sender = sysEmailTable.SenderAddr;
            outgoingEmailTable.SenderName = sysEmailTable.SenderName;
            outgoingEmailTable.Recipient = _emailAddr;
            outgoingEmailTable.Subject = "System generated PO print out notification";
            outgoingEmailTable.Priority = eMailPriority::High;
            outgoingEmailTable.WithRetries = NoYes::NO;
            outgoingEmailTable.RetryNum = 0;
            outgoingEmailTable.UserId = curUserId();
            outgoingEmailTable.Status = SysEmailStatus::Unsent;
            outgoingEmailTable.Message =  sysEmailContents;
            outgoingEmailTable.LatestStatusChangeDateTime = DateTimeUtil::getSystemDateTime();
            outgoingEmailTable.TemplateId = _emailId;
            outgoingEmailTable.insert();


            if(conLen(_binData)>0)
            {
                outgoingEmailData.clear();

                outgoingEmailData.EmailItemId = nextEmailItemId;
                outgoingEmailData.DataId = 1;
                outgoingEmailData.EmailDataType = SysEmailDataType::Attachment;
                outgoingEmailData.Data = _binData;
                filNameSplit = subStr(filename, 12, 100);

                outgoingEmailData.FileName = filNameSplit;
                outgoingEmailData.FileExtension =FileExtension;

                outgoingEmailData.insert();
            }
            info(strfmt("PO sent successfully to %1", _emailAddr));
        }
    }

    public static Str1260 map2str(Map _map, boolean _returnKey = true, str _separator = ', ')
    {
         str ret;
         MapEnumerator e = _map.getEnumerator();

        while (e.moveNext())
        {
             if (ret) ret += _separator;
             ret += any2str(_returnKey ? e.currentKey() : e.currentValue());
        }
        return ret;
    }
}

No comments:

Post a Comment

Enable and Disable Vendor invoice button on PO list and details page X++

Hi folks, This blog will be useful where vendor invoice process is required to be controlled based on certain conditions. Requirements: Proc...