web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Supply chain | Supply Chain Management, Commerce
Suggested Answer

Getting error while print the custom receipt after transaction complete.

(0) ShareShare
ReportReport
Posted on by 396

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
I have the same question (0)
  • Guanghui Profile Picture
    on at

    Hi, only from the information you provided, it is hard to identify the issue, could you please check you CRT code, if CRT code has access to DB, could you check if the DB object has the right permissions?

    Or could you please paste the whole code here then we can try to analyze or debug the code?

  • Pankaj_93 Profile Picture
    396 on at

    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;

                   }

               }

           }

       }

    }

  • Guanghui Profile Picture
    on at

    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
    396 on at

    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
    on at

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

  • Guanghui Profile Picture
    on at

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

  • Pankaj_93 Profile Picture
    396 on at

    Hi Guanghui,

    will it be a support ticket or advisory ?

    if I will log a case.

  • Suggested answer
    Guanghui Profile Picture
    on at

    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
    396 on at

    Hi Guanghui,

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

  • RhodesG Profile Picture
    25 on at

    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.

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Responsible AI policies

As AI tools become more common, we’re introducing a Responsible AI Use…

Neeraj Kumar – Community Spotlight

We are honored to recognize Neeraj Kumar as our Community Spotlight honoree for…

Leaderboard > Supply chain | Supply Chain Management, Commerce

#1
Siv Sagar Profile Picture

Siv Sagar 266 Super User 2025 Season 2

#2
Laurens vd Tang Profile Picture

Laurens vd Tang 213 Super User 2025 Season 2

#3
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 140 Super User 2025 Season 2

Last 30 days Overall leaderboard

Featured topics

Product updates

Dynamics 365 release plans