The firt part of this series in here http://daynamicsaxaptaforum.blogspot.in/2012/03/save-microsoft-dynamics-ax-2009-report.html
In the prior article I created a job to save an Axapta report to PDF into a local drive ... C:\. In this article, the code from the last article is integrated within the Run() method of a class I created called SalesConfirmReportEmail.
The SalesConfirmReportEmail class gets executed when a a user wants to send and post an Order Acknowledgement on a Sales Order. I will not discuss how the code works from the moment the user clicks ok in the SalesEditLines form, but I will point out the path that the code follows:
So, the user opens the Sales Order form, finds a record, goes to Posting > Acknowledgement , does whatever he/she needs to do and clicks OK.
In my implementation, the user can choose the output for the order confirmation report. This is, in the DocDestination drop down list he/she can choose Preview, Print, and/or Email. In this case the user wants to print the report.
As soon as the user clicks OK, the code goes through the following:
- Classes\FormMenuButton\Clicked
- Classes\FormFunctionButtonCOntrol\Clicked
- Classes\SalesFormLetter\Main
- Classes\SalesFormLetter\MainOnServer
- Classes\SalesFormLetter\Run
- Classes\SalesFormLetter_Confirm\printJournal
- Data Dictionary\Tables\CustConfirmJour\Methods\printJournal
- Classes\SalesConfirmReportEmail\postingPrint
- Classes\SalesConfirmReportEmail\run
- Classes\SysInetMail\SendMailAttach
- Classes\SysINetOutlook\AddAttachment
void printJournal(SalesFormLetter salesFormLetter = null,
RecordSortedList journalList = null)
{
Args parameters = new Args();
MenuFunction salesConfirmMenu;
;
if(salesFormLetter && salesFormLetter.SalesParmUpdate().DocDestination == glPrintType::Printer)
{
salesConfirmMenu = new MenuFunction(menuItemoutputStr(SalesConfirmation), MenuItemType::Output);
parameters.caller(salesFormLetter);
if (journalList)
{
parameters.object(journalList);
}
else
{
parameters.record(this);
}
salesConfirmMenu.run(parameters);
}
else
{
//Calling my report confirmation class
//Notice that I'm passing the salesformletter class and journal list
SalesConfirmReportEmail::postingPrint(salesFormLetter,journalList);
}
}
The following is the code for the SalesConfirmReportEmail class. It is going to be long.
class SalesConfirmReportEmail
{
RecordSortedList journalList;
glPrintType printType;
PrintJobSettings printJobSetting;
FileName fileName;
FilePath filePath;
//Earias - 2/22/2011
SalesTable salesTable;
CustConfirmJour custConfirmJour;
DirPartyId dirPartyId;
SalesQuotationTable salesQuotationTable;
Filename prtFile;
Filepath prtFilePath;
Email email;
Email CCEmail;
Telefax fax;
SysINetMail_GLBTS mail;
str _mailBody;
}
Email CCEMail(SalesTable _salesTable)
{
Email _ccEmail;
EmplTable _emplTableOutside;
EmplTable _emplTableInside;
EmplId _emplIdInside;
;
_emplIdInside = EmplTable::userId2EmplId(_salesTable.SalesResponsible);
if (_salesTable.SalesTaker == _emplIdInside)
_ccEmail = Empltable::find(_salesTable.SalesTaker).email(); //outside salesperson set with emplId
else
{
_ccEmail = Empltable::find(_salesTable.SalesTaker).Email(); //outside salesperson set with emplId
if (!_ccEmail)
_ccEmail = Empltable::find(_emplIdInside).Email(); //inside salesperson set with UserId
else
_ccEmail += "; " + Empltable::find(_emplIdInside).Email(); //inside salesperson
}
return _ccEmail;
}
public FileName parmFileName(FileName _fileName = fileName)
{
;
fileName = _fileName;
return fileName;
}
glPrintType parmglPrintType(glPrintType _printType = printType)
{
;
printType = _printType;
return printType;
}
void parmJournalList(Common _common)
{
;
journalList = FormLetter::createJournalListCopy(_common);
}
Container parmPrintJobSettings(PrintJobSettings _printJobSetting = printJobSetting)
{
;
return printJobSetting.packPrintJobSettings();
}
void printJournal(CustConfirmJour _custConfirmJour)
{
Args parameters = new Args();
MenuFunction salesConfirmMenu;
;
salesConfirmMenu = new MenuFunction(menuItemoutputStr(SalesConfirmation),MenuItemType::Output);
parameters.caller(this);
parameters.record(_custConfirmJour);
salesConfirmMenu.run(parameters);
}
void setJournalList(RecordSortedList _journalList)
{
journalList = _journalList;
}
static void main (Args _args)
{
SalesConfirmReportEmail thisClass = new SalesConfirmReportEmail();
;
breakpoint;
if(!_args.caller())
{
throw error("Invalid calling location");
}
thisClass.parmglPrintType(_args.parmEnum());
thisClass.parmJournalList(_args.record());
thisClass.run();
}
static void postingPrint(SalesFormLetter salesFormLetter,
RecordSortedList journalList)
{
SalesConfirmReportEmail thisClass = new SalesConfirmReportEmail();
;
thisClass.parmglPrintType(salesFormLetter.SalesParmUpdate().DocDestination);
thisClass.setJournalList(journalList);
thisclass.run();
}
static glPrintType reportPrintType()
{
glPrintType printType;
;
return printType;
}
public DirPartyId GetContactEmailFromDirParty(SalesTable _salesTable)
{
;
dirPartyId = CustTable::find(_salesTable.CustAccount, false).PartyId;
return dirPartyId;
}
Now, the Run() Method is very long. Here there are a few things that I want to explain before I go on. In this method I'm saving my Axapta report in a Network folder.
Yo handle this I did not want to have a constant string where the netwrok address is assigned. The reason is that I also needed to specify an alternative address in case the Network address was not available. So, if the \\NetworkLocation.com\MyFolder is not available, then we will save the file to a temp folder in the user's machine.
For this I created a table names DocuParameters as Shown below:
Then, I'm getting the PrimaryFileOutputPath from this table, if this is not Available, then I'm getting the AlternativeFileOutputPath. I guess there are a 100 ways to do this. I just choose to do it like this as it is more centralize for my purposes.
Also, after the RUN method code, I will add a method that gets the email of an Global Address Book record or PartyID.
NOTE: In the Run() method below I'm using settings that you might not need.
void run()
{
SalesId Id;
int i;
str prtFileExt = '.pdf';
SalesFormLetter salesFormLetter = SalesFormLetter::construct(DocumentStatus::Confirmation, false);
PrintJobSettings printJobSettings = new PrintJobSettings();
Args args = new Args();
DirPartyId _partyId
;
if(printType == glPrintType::Email || printType == glPrintType::Fax || printType == glPrintType::Printer)
{
//This is where I store the Network Address
prtFilepath = DocUParameters::find().PrimaryFileOutputPath;
if ( !WinApi::fileExists(prtFilePath) )
{
prtFilePath = DocUParameters::find().AlternateFileOutputPath;
}
//Setting the print parameters to file and PDF
printJobSettings.setTarget(PrintMedium::File);
printJobSettings.format(PrintFormat::PDF);
}
else
{
if(printType == glPrintType::Preview)
{
printJobSetting = new PrintJobSettings();
// printJobSetting.unpackPrinterSettings(salesFormLetter::getPrinterSettingsFormletter(DocumentStatus::Invoice));
printJobSetting.setTarget(PrintMedium::Screen);
}
}
if(journalList)
{
if(journalList.first(CustConfirmJour))
{
Do
{
if(! printType == glPrintType::Preview)
{
prtFile = custConfirmJour.SalesId;
printJobSettings.fileName(prtFilePath + prtFile + prtFileExt);
salesFormLetter.updatePrinterSettingsFormLetter(printJobSettings.packPrintJobSettings());
select firstOnly custConfirmJour
where custConfirmJour.salesid == prtFile;
args.record(custConfirmJour);
args.caller(salesFormLetter);
new MenuFunction(menuitemoutputstr(SalesConfirmation), MenuItemType::Output).run(args);
//Here we set the file name to the file name and the extension (.pdf)
prtFile = prtFile + prtFileExt;
}
else if(printType == glPrintType::Preview)
{
printJobSetting = new PrintJobSettings();
this.printJournal(CustConfirmJour);
return;
}
salesTable = CustConfirmJour.salesTable();
if(this.parmglPrintType() == glPrintType::Email)
{
_partyId = this.GetContactEmailFromDirParty(salesTable);
info(_partyId);
//Here I call a custom method to resolve the email from a Party ID
email = salesQuotationTable.contactEmail(_partyId, EmailTypes::OrderAcknowledgement);
info(email);
if(!email)
email = ContactPerson::find(salesTable.QuoteContactPersonId, false).Email;
if(!email)
{
email = CustTable::find(custConfirmJour.OrderAccount, false).Email;
//Here I set a custom error method when contacts don't have emails
//Look for this code below after this method
salesTable.SetContactEmailErrorMessage(prtFile, prtFilePath, _partyId);
return;
}
mail = new SysINetMail_GLBTS();
mail.sendMailAttach_OLD(email, CCEmail, 'Ref.: '+ CustConfirmJour.CustomerRef +'// '+ 'Acknowledgement ' + CustConfirmJour.SalesId + '','', true, prtfilePath + prtfile, prtfile);
WinApi::deleteFile(prtfilePath + prtfile);
}
if ( this.parmglPrintType() == glPrintType::Fax )
{
fax =this.parseFaxNumber( ContactPerson::find(salesTable.quoteContactPersonId,false).TeleFax);
if(!fax)
fax =this.parseFaxNumber(CustTable::find(custConfirmJour.OrderAccount,false).Telefax);
email = fax + '@j2send.com';
}
}while(journalList.next(custConfirmJour));
}
}
}
This method is in my SalesQuotationTable
Email contactEmail(DirPartyId partyId, EmailTypes type, QuotationId quoteId = '')
{
Email email;
;
//Get Email based on DirPartyId
email = AGO_Utilities::GetContactEmailFromPartyID(partyId, type, quoteId);
return email;
}
AGO_Utilities::GetContactEmailFromPartyID is a class method - see it below
public static Email GetContactEmailFromPartyID(DirPartyId partyId, EmailTypes type, QuotationId quoteId = '')
{
DirPartyRelationship dirPartyRelationship;
Boolean breakProcess = false;
DirPartyId childPartyId;
ContactPerson contactPerson;
ContactPersonId contactPersonId;
Email email = '';
;
while select dirPartyRelationship where dirPartyRelationship.ParentPartyId == partyId
{
childPartyId = dirPartyRelationship.ChildPartyId;
if(childPartyId)
{
switch(type)
{
case EmailTypes::SalesQuotes:
//Check if sales quote has a contact to it
contactPersonId = SalesQuotationTable::find(quoteId).ContactPersonId;
if(contactPersonId)
select * from contactPerson where contactPerson.ContactPersonId == contactPersonId;
else
breakProcess = true;
break;
case EmailTypes::Invoice:
select * from contactPerson where contactPerson.PartyId == childPartyId &&
contactPerson.EmailType_Invoice == NoYes::Yes;
break;
case EmailTypes::OrderAcknowledgement:
select * from contactPerson where contactPerson.PartyId == childPartyId &&
contactPerson.EmailType_OrderAcknowledgement == NoYes::Yes;
break;
case EmailTypes::ShippingMarks:
select * from contactPerson where contactPerson.PartyId == childPartyId &&
contactPerson.EmailType_ShippingMarks == NoYes::Yes;
break;
case EmailTypes::ARStatement:
select * from contactPerson where contactPerson.PartyId == childPartyId &&
contactPerson.EmailType_ARStatement == NoYes::Yes;
break;
}
if(contactPerson.Email || contactPerson.Email2)
{
if(!contactPerson.Email)
email = contactPerson.Email2;
else
email = contactPerson.Email;
break;
}
if(breakProcess)
break;
}
}
return email;
}
The next method seats in the Sales Table sets an error message when the contact does not have an email. It creates a Info log where a user can double click on the message and go directly to a record in the Contacts Table
void SetContactEmailErrorMessage(FileName fileName, FilePath filePath, DirPartyId partyId)
{
ContactPersonId contactPersonId;
SalesQuotationTable smmQuotationTable;
SysInfoAction_FormRun SysInfoAction;
;
contactPersonId = smmQuotationTable.GetContactIdFromPartyID(partyId);
WinApi::deleteFile(filePath+fileName);
if(contactPersonId || contactPersonId != '')
{
SysInfoAction = SysInfoAction_FormRun::newFormnameDesc(FormStr(ContactPersonLookup), "@AIC586");
info('@AIC583',"", SysInfoAction_TableField::newBuffer(ContactPerson::find(contactPersonId)));
}
else
Box::info('@AIC584');
}
No comments:
Post a Comment