Skip to main content

Notifications

Announcements

No record found.

Dynamics 365 Community / Forums / Commerce forum / Getting error while pr...
Commerce forum
Suggested answer

Getting error while print the custom receipt after transaction complete.

Posted on by 392

Hi All,

Hope all are doing well...

Basically, we have a requirement to print a custom receipt after the sale receipt. For this, we have written logic on the PostEndTransactiontrigger.

We are facing problem while printing the custom receipt after the salereceipt. When I debug, I found the below error.

Can anyone please help us to resolve the issue?

Error:

=> 0x80010115 - JavaScript runtime error: OLE has sent a request and is waiting for a reply
=> CommerceError
   at Error (ms-appx://microsoft.dynamics.retail.pos/Commerce.Core.js:155:21)
   at Anonymous function (ms-appx://microsoft.dynamics.retail.pos/Pos.js:17107:33)
   at Promise.onSuccess (native code)
=>string_4904
Categories:
  • Pankaj_93 Profile Picture
    Pankaj_93 392 on at
    RE: Getting error while print the custom receipt after transaction complete.

    Hi RhodesG,

    Thank you for your response....

    We are not saving any data back to database object. We are trying to print receipts for each tender details which we have used at the time of sale.

    For example:

    One item we have sold by paying 100 dollar... in cash: 20, in gift card: 50, in loyalty point: 30...

    In this case, One receipt will print as SalesReceipt along with 3 more receipts will print for this tenders..

  • RhodesG Profile Picture
    RhodesG 25 on at
    RE: Getting while save the custom receipt after transaction complete.

    From the Dynamics 365 database you can find if proper permissions are provided to the Database object.

    Once the said object is provided permissions you would not face that error.

    To find the object permissions check the CRT code.

  • Pankaj_93 Profile Picture
    Pankaj_93 392 on at
    RE: Getting while save the custom receipt after transaction complete.

    Hi Guanghui,

    Thanks a lot for your continuing support in this issue......

  • Suggested answer
    Guanghui Profile Picture
    Guanghui on at
    RE: Getting while save the custom receipt after transaction complete.

    Hi, Just log a support ticket.

    Please be aware that this is not standard functionality, so it is out of support team's scope, but I would like to try to see if we can help you to resolve this issue.

  • Pankaj_93 Profile Picture
    Pankaj_93 392 on at
    RE: Getting while save the custom receipt after transaction complete.

    Hi Guanghui,

    will it be a support ticket or advisory ?

    if I will log a case.

  • Guanghui Profile Picture
    Guanghui on at
    RE: Getting while save the custom receipt after transaction complete.

    If you are in APAC region, would you please log us a ticket for better follow-up?

  • Guanghui Profile Picture
    Guanghui on at
    RE: Getting while save the custom receipt after transaction complete.

    Sure thing, but I need some time to restore your code and try to debug.

  • Pankaj_93 Profile Picture
    Pankaj_93 392 on at
    RE: Getting while save the custom receipt after transaction complete.

    Hi Guanghui,

    Basically, I had followed the same SuspendedTransactionReceiptSample from the MS blog. I had not tried the suspendedTransactionReceiptSample. I guess in suspended transaction there will be only one receipt will generate. So I tried it in the PostEndTransaction.

    Please help me to solve this....

    Thank you in Advance...

    stay safe and healthy....

  • Guanghui Profile Picture
    Guanghui on at
    RE: Getting while save the custom receipt after transaction complete.

    Thank you.

    I need try to debug your code to see if I can find the root cause.

    But BTW, if the SuspendedTransactionReceiptSample can work in your environment, looks like most of the code are same.

  • Pankaj_93 Profile Picture
    Pankaj_93 392 on at
    RE: Getting while save the custom receipt after transaction complete.

    Hi Guanghui,

    If I set the print option as Do not print for the sales receipt, in that case custom receipt type 7  is working... as I do not have attached printer, I am saving as PDF.. When I set the sales receipt as Always print, I am getting error while printing the custom type receipts.

    Please check my code

    Typescript Code:

    -----------------------

    import * as Triggers from "PosApi/Extend/Triggers/TransactionTriggers";

    import { ObjectExtensions } from "PosApi/TypeExtensions";

    import { ClientEntities, ProxyEntities } from "PosApi/Entities";

    import { PrinterPrintRequest, PrinterPrintResponse } from "PosApi/Consume/Peripherals";

    import { GetHardwareProfileClientRequest, GetHardwareProfileClientResponse } from "PosApi/Consume/Device";

    import { GetReceiptsClientRequest, GetReceiptsClientResponse } from "PosApi/Consume/SalesOrders";

    export default class PostEndTransactionTrigger extends Triggers.PostEndTransactionTrigger {

       /**

           * Executes the trigger functionality.

           * @param {Triggers.IPostSuspendTransactionTriggerOptions} options The options provided to the trigger.

       */

       public execute(options: Triggers.IPostEndTransactionTriggerOptions): Promise<void> {

           this.context.logger.logVerbose("Executing PostEndTransactionTrigger with options " + JSON.stringify(options) + ".");

           if (ObjectExtensions.isNullOrUndefined(options) || ObjectExtensions.isNullOrUndefined(options.receipts)) {

               // This will never happen, but is included to demonstrate how to return a rejected promise when validation fails.

               let error: ClientEntities.ExtensionError

                   = new ClientEntities.ExtensionError("The options provided to the PostEndTransactionTrigger were invalid.");

               return Promise.reject(error);

           } else {

               let hardwareProfileCommon: ProxyEntities.HardwareProfile = null;

               return this.context.runtime.executeAsync(new GetHardwareProfileClientRequest())

                   .then((response: ClientEntities.ICancelableDataResult<GetHardwareProfileClientResponse>)

                       : Promise<ClientEntities.ICancelableDataResult<GetReceiptsClientResponse>> => {

                       let hardwareProfile: ProxyEntities.HardwareProfile = response.data.result;

                       hardwareProfileCommon = response.data.result;

                       // Gets the receipts.

                       let salesOrderId: string = options.receipts[0].TransactionId;

                       let receiptRetrievalCriteria: ProxyEntities.ReceiptRetrievalCriteria = {

                           IsCopy: false,

                           IsRemoteTransaction: false,

                           IsPreview: false,

                           QueryBySalesId: true,

                           ReceiptTypeValue: ProxyEntities.ReceiptType.CustomReceipt6,

                           HardwareProfileId: hardwareProfile.ProfileId

                       };

                       let getReceiptsClientRequest: GetReceiptsClientRequest<GetReceiptsClientResponse> =

                           new GetReceiptsClientRequest(salesOrderId, receiptRetrievalCriteria);

                       return this.context.runtime.executeAsync(getReceiptsClientRequest);

                   })

                   .then((response: ClientEntities.ICancelableDataResult<GetReceiptsClientResponse>)

                       : Promise<ClientEntities.ICancelableDataResult<PrinterPrintResponse>> => {

                       let receipts: ProxyEntities.Receipt[] = response.data.result;

                       // Prints the receipts.

                       let printerPrintRequest: PrinterPrintRequest<PrinterPrintResponse> = new PrinterPrintRequest(receipts);

                       return this.context.runtime.executeAsync(printerPrintRequest);

                   })

                   .then((response: ClientEntities.ICancelableDataResult<GetReceiptsClientResponse>)

                       : Promise<ClientEntities.ICancelableDataResult<GetReceiptsClientResponse>> => {

                       //let hardwareProfile: ProxyEntities.HardwareProfile = response.data.result;

                       // Gets the receipts.

                       let salesOrderId: string = options.receipts[0].TransactionId;

                       let receiptRetrievalCriteriaForCircleLoyalty: ProxyEntities.ReceiptRetrievalCriteria = {

                           IsCopy: false,

                           IsRemoteTransaction: false,

                           IsPreview: false,

                           QueryBySalesId: true,

                           ReceiptTypeValue: ProxyEntities.ReceiptType.CustomReceipt7,

                           HardwareProfileId: hardwareProfileCommon.ProfileId

                       };

                       let getReceiptsClientRequestCircleLoyalty: GetReceiptsClientRequest<GetReceiptsClientResponse> =

                           new GetReceiptsClientRequest(salesOrderId, receiptRetrievalCriteriaForCircleLoyalty);

                       return this.context.runtime.executeAsync(getReceiptsClientRequestCircleLoyalty);

                   })

                   .then((response: ClientEntities.ICancelableDataResult<GetReceiptsClientResponse>)

                       : Promise<ClientEntities.ICancelableDataResult<PrinterPrintResponse>> => {

                       let receipts: ProxyEntities.Receipt[] = response.data.result;

                       // Prints the receipts.

                       let printerPrintRequest: PrinterPrintRequest<PrinterPrintResponse> = new PrinterPrintRequest(receipts);

                       return this.context.runtime.executeAsync(printerPrintRequest);

                   })

                   .then((): Promise<void> => {

                       // Resolves to a void result when fulfilled.

                       return Promise.resolve();

                   }).catch((reason: any): Promise<void> => {

                       // Resolves to a void result when rejected. This matches existing POS printing behavior.

                       this.context.logger.logError("PostEndTransactionTrigger execute error: " + JSON.stringify(reason));

                       return Promise.resolve();

                   });

           }

       }

    }

    CRT:

    ---------------------

    /**

    * SAMPLE CODE NOTICE

    *

    * THIS SAMPLE CODE IS MADE AVAILABLE AS IS.  MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,

    * OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.

    * THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.

    * NO TECHNICAL SUPPORT IS PROVIDED.  YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.

    */

    namespace Contoso

    {

       namespace Commerce.Runtime.ReceiptsSample

       {

           using System;

           using System.Collections.Generic;

           using System.Collections.ObjectModel;

           using Microsoft.Dynamics.Commerce.Runtime;

           using Microsoft.Dynamics.Commerce.Runtime.DataModel;

           using Microsoft.Dynamics.Commerce.Runtime.Messages;

           using Microsoft.Dynamics.Commerce.Runtime.Services.Messages;

           using Microsoft.Dynamics.Commerce.Runtime.Workflow;

           /// <summary>

           /// The request handler for GetCustomReceiptsRequestHandler class.

           /// </summary>

           /// <remarks>

           /// This is a example of how to print custom types of receipts. In this example we are mimicking following scenario:

           /// if one or more special items were sold in a transaction, then we need to print a special custom receipt for each

           /// of these special items along with all original sales receipts.

           /// Here are some points of how to do this:

           /// 1. The user should only handle <see cref="ReceiptType"/> 'CustomReceiptType' here. All other types of receipts

           ///    are handled by CommerceRuntime.

           /// 2. The most important thing to do here is preparing the data which will be used to render the receipt later.

           /// 3. So far, only sales-transaction-based custom receipts are supported. This means the data your prepared at step 2

           ///    must be a <see cref="SalesOrder"/> object.

           /// </remarks>

           public class GetCustomReceiptsRequestHandler : SingleRequestHandler<GetCustomReceiptsRequest, GetReceiptResponse>

           {

               /// <summary>

               /// Processes the GetCustomReceiptsRequest to return the set of receipts. The request should not be null.

               /// </summary>

               /// <param name="request">The request parameter.</param>

               /// <returns>The GetReceiptResponse.</returns>

               protected override GetReceiptResponse Process(GetCustomReceiptsRequest request)

               {

                   ThrowIf.Null(request, "request");

                   ThrowIf.Null(request.ReceiptRetrievalCriteria, "request.ReceiptRetrievalCriteria");

                   // 1. We need to get the sales order that we are print receipts for.

                   var getCustomReceiptsRequest = new GetSalesOrderDetailsByTransactionIdServiceRequest(request.TransactionId, SearchLocation.Local);

                   var getSalesOrderDetailsServiceResponse = this.Context.Execute<GetSalesOrderDetailsServiceResponse>(getCustomReceiptsRequest);

                   if (getSalesOrderDetailsServiceResponse == null ||

                       getSalesOrderDetailsServiceResponse.SalesOrder == null)

                   {

                       throw new DataValidationException(

                           DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_ObjectNotFound,

                           string.Format("Unable to get the sales order created. ID: {0}", request.TransactionId));

                   }

                   SalesOrder salesOrder = getSalesOrderDetailsServiceResponse.SalesOrder;

                   Collection<Receipt> result = new Collection<Receipt>();

                   // 2. Now we can handle any additional receipt here.

                   switch (request.ReceiptRetrievalCriteria.ReceiptType)

                   {

                       // An example of getting custom receipts.

                       case ReceiptType.CustomReceipt6:

                           {

                               IEnumerable<Receipt> customReceipts = this.GetCustomReceipts(salesOrder, request.ReceiptRetrievalCriteria);

                               result.AddRange(customReceipts);

                           }

                           break;

                       case ReceiptType.CustomReceipt7:

                           {

                               IEnumerable<Receipt> customReceipts = this.GetCustomTenderReceipts(salesOrder, request.ReceiptRetrievalCriteria);

                               result.AddRange(customReceipts);

                           }

                           break;

                       default:

                           // Add more logic to handle more types of custom receipt types.

                           break;

                   }

                   return new GetReceiptResponse(new ReadOnlyCollection<Receipt>(result));

               }

               /// <summary>

               /// An example to print all special custom receipts. If there are multiple special items

               /// were sold in a transaction, then we print a custom receipt for each of these items.

               /// </summary>

               /// <param name="salesOrder">The sales order that we are printing receipts for.</param>

               /// <param name="criteria">The receipt retrieval criteria.</param>

               /// <returns>A collection of receipts.</returns>

               private Collection<Receipt> GetCustomReceipts(SalesOrder salesOrder, ReceiptRetrievalCriteria criteria)

               {

                   // Back up and clear existing sales lines because we want to print a custom receipt for each one of the sales lines.

                   Collection<SalesLine> originalSalesLines = salesOrder.SalesLines;

                   salesOrder.SalesLines = new Collection<SalesLine>();

                   Collection<Receipt> result = new Collection<Receipt>();

                   foreach (SalesLine salesLine in originalSalesLines)

                   {

                       // Check if the item is a special item.

                       if (this.IsGiftCardItem(salesLine))

                       {

                           // Add this special item back to the sales order so that we can print the custom receipt for this sales line.

                           salesOrder.SalesLines.Add(salesLine);

                           // Call receipt service to get the custom receipt.

                           var getReceiptServiceRequest = new GetReceiptServiceRequest(

                                   salesOrder,

                                   new Collection<ReceiptType> { criteria.ReceiptType },

                                   salesOrder.TenderLines,

                                   criteria.IsCopy,

                                   criteria.IsPreview,

                                   criteria.HardwareProfileId);

                           ReadOnlyCollection<Receipt> customReceipts = this.Context.Execute<GetReceiptServiceResponse>(getReceiptServiceRequest).Receipts;

                           // Add the custom receipt to the result collection.

                           result.AddRange(customReceipts);

                           // Clean the sales lines.

                           salesOrder.SalesLines.Clear();

                       }

                   }

                   return result;

               }

               private Collection<Receipt> GetCustomTenderReceipts(SalesOrder salesOrder, ReceiptRetrievalCriteria criteria)

               {

                   Collection<TenderLine> originalTenderLines = salesOrder.TenderLines;

                   salesOrder.TenderLines = new Collection<TenderLine>();

                   Collection<Receipt> result = new Collection<Receipt>();

                   foreach (TenderLine tenderLine in originalTenderLines)

                   {

                       if (IsCircleLoyalty(tenderLine))

                       {

                           salesOrder.TenderLines.Add(tenderLine);

                           var getReceiptServiceRequest = new GetReceiptServiceRequest(

                                   salesOrder,

                                   new Collection<ReceiptType> { criteria.ReceiptType },

                                   salesOrder.TenderLines,

                                   criteria.IsCopy,

                                   criteria.IsPreview,

                                   criteria.HardwareProfileId);

                           ReadOnlyCollection<Receipt> customReceipts = this.Context.Execute<GetReceiptServiceResponse>(getReceiptServiceRequest).Receipts;

                           // Add the custom receipt to the result collection.

                           result.AddRange(customReceipts);

                           // Clean the sales lines.

                           salesOrder.TenderLines.Clear();

                       }

                   }

                   return result;

               }

               /// <summary>

               /// A fake logic of determining if a sales line is special or not.

               /// </summary>

               /// <param name="salesLine">The sales line.</param>

               /// <returns>True if the item is special, false otherwise.</returns>

               private bool IsSpecialItem(SalesLine salesLine)

               {

                   if (salesLine.ItemId.StartsWith("0", StringComparison.OrdinalIgnoreCase))

                   {

                       return true;

                   }

                   else

                   {

                       return false;

                   }

               }

               private bool IsGiftCardItem(SalesLine salesLine)

               {

                   if (salesLine.ItemId=="7777")

                   {

                       return true;

                   }

                   else

                   {

                       return false;

                   }

               }

               private bool IsCircleLoyalty(TenderLine tenderLine)

               {

                   if (tenderLine.TenderTypeId == "16")

                   {

                       return true;

                   }

                   else

                   {

                       return false;

                   }

               }

           }

       }

    }

Helpful resources

Quick Links

Replay now available! Dynamics 365 Community Call (CRM Edition)

Catch up on the first D365 Community Call held on 7/10

Community Spotlight of the Month

Kudos to Saurav Dhyani!

Congratulations to the June Top 10 community leaders!

These stars go above and beyond . . .

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 288,513 Super User

#2
Martin Dráb Profile Picture

Martin Dráb 225,862 Super User

#3
nmaenpaa Profile Picture

nmaenpaa 101,148

Leaderboard

Featured topics

Product updates

Dynamics 365 release plans