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

Announcements

No record found.

News and Announcements icon
Community site session details

Community site session details

Session Id :
Small and medium business | Business Central, N...
Suggested Answer

To create or convert sales order to a sales quote

(3) ShareShare
ReportReport
Posted on by 129

Hello everyone,

 

I am working on a task to create a job queue that processes all released sales quotes and creates corresponding sales orders. I am using an event subscriber on the Sales Quote table, specifically the OnAfterRun trigger, to release the sales order upon processing.

The requirement is that the job should not be interrupted if an error occurs. For this, I am using the TRY function to handle exceptions.

However, I need some clarification regarding error handling: If an error occurs during the release of a sales order, I want to ensure that the associated sales quote is retained and the partially created sales order is deleted.

How can I achieve this in AL (or Dynamics 365 Business Central)? Specifically, I need guidance on how to manage the sales quote and sales order in such a way that if an error happens, the sales quote remains intact while the sales order is rolled back or deleted.

Any suggestions or best practices for handling this scenario would be greatly appreciated!

I have the same question (0)
  • Martin Dráb Profile Picture
    239,647 Most Valuable Professional on at
    Moved from Integration, Dataverse, and general topics forum.
  • Suggested answer
    Mansi Soni Profile Picture
    9,774 Super User 2026 Season 1 on at
  • Suggested answer
    Jainam M. Kothari Profile Picture
    16,686 Super User 2026 Season 1 on at
  • TB-28100618-0 Profile Picture
    129 on at
    Thanks for the answers!
    I tried both but it ends up like creating sales order but not released and sales quote is deleted.

     
    codeunit 90916 SO_job
    {
        trigger OnRun()
        begin
            createso();
        end;
     
        local procedure createso()
        var
            mydatetime: DateTime;
            mydate: date;
            createsroCodeunit: Codeunit SalesReturnOrderProcessor;
            salesheader: Record "Sales Header";
            sro: record "Sales Header";
            salesorederheader: Record "Sales Header";
        begin
            mydate := CalcDate('<-1D>', Today);
            mydatetime := CreateDateTime(mydate, 0T);
            SalesHeader.Reset();
            SalesHeader.SetRange(SystemCreatedAt, mydatetime, CurrentDateTime);
            SalesHeader.SetFilter("Document Type", '=%1', SalesHeader."Document Type"::Quote);
            SalesHeader.SetFilter(Status, '=%1', SalesHeader.Status::Released);
            salesheader.SetFilter("Order Type", '=%1', SalesHeader."Order Type"::"SALES");
            salesheader.SetFilter("Responsibility Center", '=%1', 'SALESM');
            if salesheader.Find('-') then begin
                Message(Format(salesheader.Count));
                repeat
                    message(format(salesheader."No."));
                    if not CreateSalesOrder(salesheader) then begin
                        salesorederheader.Reset();
                        salesorederheader.SetRange("Quote No.", salesheader."No.");
                        Message(getlasterrortext());
     
                        if salesorederheader.FindSet() then begin
                            Message(Format(salesorederheader."No."));
                            salesorederheader."SO Error" := GetLastErrorText();
                            salesorederheader.Modify();
                            Message(Format(salesorederheader."SO Error"));
     
                        end;
                        // salesheader."SO Error" := GetLastErrorText();
     
                        // salesheader.Modify();
                    end;
                until salesheader.Next() = 0;
            end;
        end;
     
        [TryFunction]
        procedure CreateSalesOrder(SalesHeader: Record "Sales Header")
        var
            SalesQuoteLine: Record "Sales Line";
            SalesOrderTemp: Record "Sales Header";
            SalesOrderLine: Record "Sales Line";
            NewReturnOrderNo: Code[20];
            ReleaseSalesDoc: Codeunit "Release Sales Document";
            ReturnCode: Record "Return Reason";
            ApprovalsMgmt: Codeunit "Approvals Mgmt.";
            SalesQuoteToOrder: Codeunit "Sales-Quote to Order";
        begin
            if ApprovalsMgmt.PrePostApprovalCheckSales(SalesHeader) then
                SalesQuoteToOrder.run(SalesHeader)
     
        end;


     
        var
            myInt: Integer;
    }
  • Gerardo Rentería García Profile Picture
    26,842 Most Valuable Professional on at

    Hi, good day
    I hope this can help you, and give you some hints.

    How to Convert Sales Quotes to Sales Order Using Power Automate? - MADHDA Business Solutions - a Microsoft Partner

    Best Regards
    Gerardo

  • Suggested answer
    Ramiz Profile Picture
    630 on at
    Hi,
    Try this.
     
    codeunit 50103 "SO Job"
    {
        trigger OnRun()
        begin
            CreateSO();
        end;
    
        local procedure CreateSO()
        var
            SalesHeader: Record "Sales Header";
            SRO: Record "Sales Header";
            SalesOrderHeader: Record "Sales Header";
            MyDateTime: DateTime;
            MyDate: Date;
        begin
            MyDate := CalcDate('<-1D>', Today);
            MyDateTime := CreateDateTime(MyDate, 0T);
            SalesHeader.Reset();
            SalesHeader.SetRange(SystemCreatedAt, MyDateTime, CurrentDateTime);
            SalesHeader.SetFilter("Document Type", '=%1', SalesHeader."Document Type"::Quote);
            SalesHeader.SetFilter(Status, '=%1', SalesHeader.Status::Released);
            if GuiAllowed then
                Message(Format(SalesHeader.Count));
            if SalesHeader.FindSet() then
                repeat
                    Message(Format(SalesHeader."No."));
                    if not CreateSalesOrder(SalesHeader) then begin
                        SalesOrderHeader.Reset();
                        SalesOrderHeader.SetRange("Quote No.", SalesHeader."No.");
                        if GuiAllowed then
                            Message(getlasterrortext());
    
                        if SalesOrderHeader.FindSet() then begin
                            if GuiAllowed then
                                Message(Format(SalesOrderHeader."No."));
                            SalesOrderHeader."SO Error" := GetLastErrorText();
                            SalesOrderHeader.Modify();
                            if GuiAllowed then
                                Message(Format(SalesOrderHeader."SO Error"));
    
                        end;
                    end;
                until SalesHeader.Next() = 0;
        end;
    
        local procedure CreateSalesOrder(var SalesHeader: Record "Sales Header"): Boolean
        var
            SalesQuoteLine: Record "Sales Line";
            SalesOrderTemp: Record "Sales Header";
            SalesOrderLine: Record "Sales Line";
            NewReturnOrderNo: Code[20];
            ReleaseSalesDoc: Codeunit "Release Sales Document";
            ApprovalsMgmt: Codeunit "Approvals Mgmt.";
            SalesQuoteToOrder: Codeunit "Sales-Quote to Order";
        begin
            if ApprovalsMgmt.PrePostApprovalCheckSales(SalesHeader) then
                if SalesQuoteToOrder.Run(SalesHeader) then
                    exit(true);
            exit(false);
        end;
     
     
    codeunit 50104 "Release Sales Doc"
    {
        TableNo = "Sales Header";
    
        trigger OnRun()
        var
            ReleaseSalesDoc: Codeunit "Release Sales Document";
        begin
            ReleaseSalesDoc.PerformManualRelease(Rec);
        end;
    
    }
     
    [EventSubscriber(ObjectType::Codeunit, Codeunit::"Sales-Quote to Order", OnBeforeDeleteSalesQuote, '', false, false)]
        local procedure OnAfterOnRun(var QuoteSalesHeader: Record "Sales Header"; var OrderSalesHeader: Record "Sales Header"; var IsHandled: Boolean; var SalesQuoteLine: Record "Sales Line")
        var
            ReleaseSalesDoc: Codeunit "Release Sales Doc";
        begin
            if not ReleaseSalesDoc.Run(OrderSalesHeader) then
                IsHandled := true;
        end;
  • Vahid Ghafarpour Profile Picture
    12,264 on at
    If any of the responses helped resolve your issue, please take a moment to mark the best answer. This helps others in the community quickly find solutions to similar problems.

    To do this, simply click the "Does this answer your question?" button on the most helpful response and like the helpful posts. If your issue is still unresolved, feel free to provide more details so the community can assist further!

    Thanks for being an active part of the Dynamics 365 Community! 😊

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

Introducing the 2026 Season 1 community Super Users

Congratulations to our 2026 Super Stars!

Meet the Microsoft Dynamics 365 Contact Center Champions

We are thrilled to have these Champions in our Community!

Congratulations to the April Top 10 Community Leaders

These are the community rock stars!

Leaderboard > Small and medium business | Business Central, NAV, RMS

#1
OussamaSabbouh Profile Picture

OussamaSabbouh 2,024 Super User 2026 Season 1

#1
OussamaSabbouh Profile Picture

OussamaSabbouh 2,024 Super User 2026 Season 1

#3
YUN ZHU Profile Picture

YUN ZHU 1,383 Super User 2026 Season 1

Last 30 days Overall leaderboard

Featured topics

Microsoft Training Manuals

Product updates

Dynamics 365 release plans