26.10.2015, 12:11 | #1 |
Участник
|
patrickmouwen: Dynamics AX Retail 3rd party POS and E-commerce integration – Control dashboard
Источник: http://patrickmouwen.com/technicalde...rol-dashboard/
============== In my main blog post regarding Dynamics AX Retail/3rd party integration I mentioned leveraging Real Time Service to allow middleware (like Microsoft BizTalk) and 3rd party systems to report to AX on the results of their actions. As the meta data is written into the standard Dynamics AX Retail download sessions and upload sessions forms, these forms will now serve system administrators to have visibility and control even beyond their the Dynamics AX Retail CDX landscape (CDX -> see rectangle in the middle, beyond CDX -> bottom rectangle): In this blog I’ll provide the X++ source code to enable this and I’ll mention some tiny features I added to the download sessions and upload sessions forms to maximize control on our 3rd party integration. First I’ll introduce you to the topic by explaining a bit more on how to extend Real Time Service for access from 3rd party systems. How to extend Real Time Service What I like most about Real Time Service is that it provides a single-point-of-access to any method in AX from the outside world. With ‘single-point-of-access’ I mean that with Real Time Service we don’t need to expose an endless number of services if for example we want to get customer information, create a customer and cancel an order – we can stick to 1 service only as the AX method we want to call into through the service is a parameter on the service. So if we want to create a customer in AX we tell the service to invoke the RetailTransactionService::newCustomer method and we provide the service with the input parameters the respective method in AX expects: Message for calling the Real Time Service (newCustomer method) = The “sender” AX HQ newCustomer method = The “receiver” So basically you can call into any method in AX from 3rd party systems just by passing the right parameters and sending the information in the right message format. In a later blog I’ll provide more details in this particular area – for now I stick to mentioning some basic ‘rules of play’:
With this custom method (see source code below), both Retail > Inquiries > Commerce data exchange > Upload sessions and Download sessions table/forms are served. This is directed by the downloadMessage boolean field which is 1 (true) if the respective interface flow is a download flow (AX -> native AX/3rd party) and 0 (false) if the respective interface flow is an upload flow (naïve AX/3rd party). The artifacts prefixed with ‘pmo’ are discussed in the next section of this blog. First I’ll list you the input/output variables for the method – the array element type indicates what the type of parameter is that your XML message to Real Time Service requires for the variable. Note for the X++ code that I included many validations to ensure errors are not raised due to XML variable type to AX variable type conversion issues. /// /// Method is added by PMOU (16.06.2015) /// Method is used for creating a RetailCDXDataStoreSession record which reflects CDX meta data /// BizTalk leverages the method to report on the result of its part of the AX/3rd party channel interface chain /// In doing so, system administrators have complete visibility and control across the complete interface chain including integration to 3rd party channels /// /// /// Container with entity keys /// public static container newRetailCDXMetaDataRecord(boolean downloadMessage, RetailCDXSharePath sDataFileOutputPath, RetailCDXDataGroupRefRecId sDatagroupRecId, RetailConnJobId sJobId, RetailCDXRowsAffected sRowsAffected, RetailCDXScheduleRefRecId sScheduleRecId, RetailCDXSessionNumber sSessionNumber, RetailCDXDownloadSessionStatus sDownloadStatus, pmoRetailCDXLinkedSessionRefRecId sdsLinkedSessionRecId, RetailCDXDataStoreRefRecId sdsDataStoreRecId, str sdsDateApplied, str sdsDateDownloaded, str sdsDateRequested, RetailCDXMonDataSyncMessage sdsMessage, RetailCDXDownloadSessionStatus sdsDownloadStatus, RetailCDXCheckSum uCheckSum, RetailCDXDataStoreRefRecId uDataStoreRecId, str uDateCreated, str uDateUploaded, RetailCDXFileSize uFileSize, RetailCDXHqUploadSessionID uHQUploadSessionId, RetailConnJobId uJobId, RetailCDXMonDataSyncMessage uMessage, RetailCDXUploadSessionRerun uRerun, RetailCDXSessionNumber uRerunForSessionId, RetailCDXRowsAffected uRowsAffected, RetailCDXScheduleRefRecId uScheduleRecId, RetailCDXUploadSessionStatus uUploadStatus, RetailCDXTryCount uTryCount, RetailCDXPacketFilePath uUploadPath, RetailCDXSessionNumber uUploadSessionId, pmoRetailCDXLinkedSessionRefRecId uLinkedSessionRecId, pmoRetailCDXDataSource uDataSource) { boolean success = false; str error = ”; Counter infologline = infolog.num(); int fromLine; str xmlResult = ”; container tmpResult; RetailCDXDownloadSessionRefRecId downloadSessionRecId; RetailCDXDownloadSession retailCDXDownloadSession; retailCDXDownloadSessionDataStore retailCDXDownloadSessionDataStore; RetailCDXUploadSession retailCDXUploadSession; RetailCDXUploadSessionLog retailCDXUploadSessionLog; RefRecId sessionRecId; RetailCDXDateApplied sdsdateAppliedUTC; //UTCDateTime RetailCDXDateDownloaded sdsdateDownloadedUTC; //UTCDateTime RetailCDXDateRequested sdsdateRequestedUTC; //UTCDateTime RetailCDXDateCreated udateCreatedUTC; //UTCDateTime RetailCDXDateUploaded udateUploadedUTC; //UTCDateTime try { fromLine = Global::infologLine(); // Validate if this is an AX inbound or outbound flow if (downloadMessage == true) { // If SessionNumber is 0 then create a new session if (ssessionNumber == 0) { ssessionNumber = RetailCDXSessionIDGenerator::getNextSession(); } if (ssessionNumber > 0 && sjobId && sdatagroupRecId && sdsdataStoreRecId) { // Populate table RetailCDXDownloadSession ttsBegin; retailCDXDownloadSession.clear(); retailCDXDownloadSession.initValue(); if (sDataFileOutputPath) { retailCDXDownloadSession.DataFileOutputPath = sDataFileOutputPath; } retailCDXDownloadSession.DataGroup = sdatagroupRecId; retailCDXDownloadSession.JobID = sjobId; if (srowsAffected > 0) { retailCDXDownloadSession.RowsAffected = srowsaffected; } if (sscheduleRecId) { retailCDXDownloadSession.Schedule = sscheduleRecId; } retailCDXDownloadSession.Session = ssessionNumber; if (sdownloadStatus) { retailCDXDownloadSession.Status = sdownloadStatus; } retailCDXDownloadSession.insert(); sessionRecId = retailCDXDownloadSession.RecId; ttsCommit; // Populate table retailCDXDownloadSessionDataStore ttsBegin; retailCDXDownloadSessionDataStore.clear(); retailCDXDownloadSessionDataStore.initValue(); if (sdslinkedSessionRecId) { retailCDXDownloadSessionDataStore.pmoLinkedSession = sdslinkedSessionRecId; } retailCDXDownloadSessionDataStore.DataStore = sdsdataStoreRecId; if (sdsdateApplied) { sdsdateAppliedUTC = str2datetime(sdsdateApplied,123); retailCDXDownloadSessionDataStore.DateApplied = sdsdateAppliedUTC; } retailCDXDownloadSessionDataStore.Session = sessionRecId; if (sdsdateDownloaded) { sdsdateDownloadedUTC = str2datetime(sdsdateDownloaded,123); retailCDXDownloadSessionDataStore.DateDownloaded = sdsdateDownloadedUTC; } if (sdsdateRequested) { sdsdateRequestedUTC = str2datetime(sdsdateRequested,123); retailCDXDownloadSessionDataStore.dateRequested = sdsdateRequestedUTC; } if (sdsmessage) { retailCDXDownloadSessionDataStore.Message = sdsmessage; } if (sdsdownloadStatus) { retailCDXDownloadSessionDataStore.Status = sdsdownloadStatus; } if (uDataSource) { retailCDXDownloadSessionDataStore.pmoDataSource = uDataSource; } retailCDXDownloadSessionDataStore.insert(); ttsCommit; success = true; } else { error = ‘@PMO17’; success = false; } } else { // If SessionNumber is 0 then create a new session if (uUploadSessionId == 0) { // The upload session is synched from AsyncServerHeadOffice\dbo.UPLOADSESSION, so a new session ID should not interfere with the SQL ID range uUploadSessionId = RetailCDXUploadSession::getNextBizTalkSession(); } if (uUploadSessionId > 0 && uJobId && uDataStoreRecId) { // Populate table RetailCDXUploadSession ttsBegin; retailCDXUploadSession.clear(); retailCDXUploadSession.initValue(); if (uUploadPath) { retailCDXUploadSession.UploadPath = uUploadPath; } retailCDXUploadSession.DataStore = uDataStoreRecId; retailCDXUploadSession.JobId = uJobId; if (uRowsAffected > 0) { retailCDXUploadSession.RowsAffected = uRowsAffected; } if (uScheduleRecId) { retailCDXUploadSession.Schedule = uScheduleRecId; } retailCDXUploadSession.UploadSessionId = uUploadSessionId; if (uUploadStatus) { retailCDXUploadSession.Status = uUploadStatus; } if (uCheckSum) { retailCDXUploadSession.CheckSum = uCheckSum; } if (uDateCreated) { uDateCreatedUTC = str2datetime(uDateCreated,123); retailCDXUploadSession.DateCreated = uDateCreatedUTC; } if (uDateUploaded) { uDateUploadedUTC = str2datetime(uDateUploaded,123); retailCDXUploadSession.DateUploaded = uDateUploadedUTC; } if (uFileSize) { retailCDXUploadSession.FileSize = uFileSize; } if (uHQUploadSessionId) { retailCDXUploadSession.HqUploadSessionId = uHQUploadSessionId; } if (uMessage) { retailCDXUploadSession.Message = uMessage; } if (uTryCount > 0) { retailCDXUploadSession.TryCount= uTryCount; } if (uRerun > 0) { retailCDXUploadSession.Rerun= uRerun; } if (uRerunForSessionId) { retailCDXUploadSession.RerunFor = uRerunForSessionId; } if (uDataSource) { retailCDXUploadSession.pmoDataSource = uDataSource; } retailCDXUploadSession.insert(); ttsCommit; // Populate table RetailCDXUploadSessionLog ttsBegin; retailCDXUploadSessionLog.clear(); retailCDXUploadSessionLog.initValue(); retailCDXUploadSessionLog.DataStore = uDataStoreRecId; if (uDateCreated) { uDateCreatedUTC = str2datetime(uDateCreated,123); retailCDXUploadSessionLog.DateCreated = uDateCreatedUTC; } if (uMessage) { retailCDXUploadSessionLog.Message = uMessage; } if (uUploadStatus) { retailCDXUploadSessionLog.Status = uUploadStatus; } retailCDXUploadSessionLog.UploadSessionId = uUploadSessionId; retailCDXUploadSessionLog.insert(); ttsCommit; success = true; } else { error = ‘@PMO17’; success = false; } } } catch(Exception::Error) { ttsabort; error = RetailTransactionService::getInfologMessages(fromLine); RetailTracer::Error(‘RetailTransactionServiceEx’,funcName(),error); success = false; } tmpResult = [success, error]; return tmpResult; } Enhancements to the Download session and Upload session form In the Upload session form, the Message field is not visible by default. As this field will contain any positive or negative feedback from our middleware or 3rd party system, this is the first thing to change: As shown in the picture, in both Upload and Download session form I’ve added the Origin field which indicates which link of the interface chain is reporting to us (see second column). Last but not least I’ve added a Linked download session field to the Download session form which shows which session (read: record in the Download session form) the current record followed up on. In this way, you can easy filter the form to have all the meta data as reported by the different chains of the complete interface flow in one overview. I hope this has shown you how powerful Dynamics AX for Retail can also be leveraged for 3rd party sales channel integrations. Happy DAX’ing! Patrick Het bericht Dynamics AX Retail 3rd party POS and E-commerce integration – Control dashboard verscheen eerst op Patrick Mouwen. Источник: http://patrickmouwen.com/technicalde...rol-dashboard/
__________________
Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору. |
|