Record insert stops after first error - and GETLASTERRORTEXT

samantha73samantha73 Member Posts: 106
Hi Guys
I have been trying to insert a batch of records (quotes copied to orders) using a codeunit and see if anyone can help. This is just a proof of concept and if it works I want to import an excel file to a user table and run similar code to create orders. In a nutshell, what I want is the system to continue after the error, and if possible write errors to a user table. So below is the code pattern I think I require:

if Item.findset repeat
if MyCodeUnit.run(Item) then begin
WriteLog( GETLASTERRORTEXT);
end;
until Item.next = 0;


Now with my code below I don't know how to pass a parameter (sales header) to the code unit. The first code unit should run the second code unit per each header record. Sales line loop is designed to fail for some records as a test.

Code that purposely fails if more than one line on sales quote:

codeunit 50020 U_LastError
{

trigger OnRun()
var
SalesQuote: Record "Sales Header";
begin
SalesQuote.Reset();
SalesQuote.SetRange(Status, SalesQuote.Status::Open);
SalesQuote.Setrange("Document Type", SalesQuote."Document Type"::Quote);
if SalesQuote.FindSet(true) then
repeat

if CreateOrderCodeUnit.Run() then //need to pass SalesQuote as parameter?
message('Message %1', GetLastErrorText());
Commit();
until SalesQuote.Next() = 0;
end;

var
CreateOrderCodeUnit: Codeunit U_CreateSalesOrderTest;
SalesQuote: Record "Sales Header";
}

codeunit 50013 U_CreateSalesOrderTest
{
var
SalesHeader: Record "Sales Header";
SalesLine: Record "Sales Line";
SalesQuoteHeader: Record "Sales Header";
SalesQuoteLine: record "Sales Line";
NextLineNo: Integer;


trigger OnRun()

begin
CreateSO(SalesQuoteHeader);

end;

procedure CreateSO(var SalesQuoteHeader: Record "Sales Header")
Begin
Clear(SalesHeader);
SalesHeader.Init;
SalesHeader.VALIDATE("Document Type", SalesHeader."Document Type"::Order);
SalesHeader.Validate("No. Series", 'S-ORD2');
// insert the new record into the table
SalesHeader.validate("Sell-to Customer No.", SalesQuoteHeader."Sell-to Customer No.");
SalesHeader.Validate("External Document No.", SalesQuoteHeader."External Document No.");
SalesHeader.Validate("Requested Delivery Date", SalesQuoteHeader."Requested Delivery Date");
SalesHeader.INSERT(TRUE);

SalesQuoteLine.Reset();
SalesQuoteLine.SetRange("Document Type", SalesQuoteLine."Document Type"::Quote);
SalesQuoteLine.SetRange("Document No.", SalesQuoteHeader."No.");
if SalesQuoteLine.FindSet() then begin
NextLineNo := 0;
if SalesLine.Findfirst() then
repeat
Clear(SalesLine);
salesLine.Init();
SalesLine."Document No." := SalesHeader."No.";
SalesLine."Document Type" := SalesHeader."Document Type";
nextLineNo := nextLineNo + 10000;
salesLine."Line No." := nextLineNo;

SalesLine.Validate(Type, SalesQuoteLine.Type);
SalesLine.validate("No.", SalesQuoteLine."No.");
SalesLine.Validate(Description, SalesQuoteLine.Description);
SalesLine.validate(Quantity, SalesQuoteLine.Quantity);
SalesLine.INSERT(true);

NextLineNo := 0;//TEST ONLY to FAIL with duplicate line no

until SalesQuoteLine.Next() = 0;
end;
end;
}

Comments

  • bbrownbbrown Member Posts: 3,268
    Any time you want to trap the error from a piece of code, log it can continue you need to place the code in its own codeunit. The GETLASTERROR only functions for code run from the OnRun trigger.

    There are no bugs - only undocumented features.
  • samantha73samantha73 Member Posts: 106
    Hi Guys
    Ok I looked at how base app sales-post batch job is coded and modified my code. Now it run through all records and import valid ones. Problem is I get a pop up "OnAfterValidate Your Ref" when I try to write back something to failed record - in this case failed Sales Quote. I think it is standard practis to mark records as success for failure. Here's the latest code:

    codeunit 50020 U_CreateSalesOrderBatch
    {
    trigger OnRun()
    begin
    CreateSalesOrderBatch();
    end;

    var
    local procedure CreateSalesOrderBatch()
    var
    SalesReceivablesSetup: Record "Sales & Receivables Setup";
    SalesHeader: Record "Sales Header";
    ErrorMessageManagement: Codeunit "Error Message Management";
    begin
    LockTimeout(false);
    SalesHeader.SetRange("Document type", SalesHeader."Document Type"::Quote);
    if SalesHeader.FindSet() then
    repeat
    if NOT Codeunit.Run(Codeunit::U_CreateSalesOrder, SalesHeader) then begin

    SalesHeader.Validate("Your Reference", 'Error Test');
    SalesHeader.Modify(True);
    Commit();
    ErrorMessageManagement.LogLastError();
    Commit();

    end
    until SalesHeader.Next() = 0;
    end;
    }

    codeunit 50013 U_CreateSalesOrder
    {
    TableNo = "Sales Header";

    trigger OnRun()

    begin
    CreateSo(Rec);
    end;

    procedure CreateSO(var SalesQuoteHeader: Record "Sales Header")
    var
    SalesHeader: Record "Sales Header";
    SalesLine: Record "Sales Line";
    SalesQuoteLine: record "Sales Line";
    NextLineNo: Integer;
    Begin
    Clear(SalesHeader);
    SalesHeader.Init;
    SalesHeader.VALIDATE("Document Type", SalesHeader."Document Type"::Order);
    SalesHeader.Validate("No. Series", 'S-ORD');
    SalesHeader.validate("Sell-to Customer No.", SalesQuoteHeader."Sell-to Customer No.");
    SalesHeader.Validate("External Document No.", SalesQuoteHeader."External Document No.");
    SalesHeader.Validate("Requested Delivery Date", SalesQuoteHeader."Requested Delivery Date");
    SalesHeader.INSERT(TRUE);

    SalesQuoteLine.Reset();
    SalesQuoteLine.SetRange("Document Type", SalesQuoteLine."Document Type"::Quote);
    SalesQuoteLine.SetRange("Document No.", SalesQuoteHeader."No.");
    if SalesQuoteLine.FindSet() then begin
    NextLineNo := 0;
    if SalesLine.Findfirst() then
    repeat
    Clear(SalesLine);
    salesLine.Init();
    SalesLine."Document No." := SalesHeader."No.";
    SalesLine."Document Type" := SalesHeader."Document Type";
    nextLineNo := nextLineNo + 10000;
    salesLine."Line No." := nextLineNo;

    SalesLine.Validate(Type, SalesQuoteLine.Type);
    SalesLine.validate("No.", SalesQuoteLine."No.");
    SalesLine.Validate(Description, SalesQuoteLine.Description);
    SalesLine.validate(Quantity, SalesQuoteLine.Quantity);
    SalesLine.INSERT(true);

    NextLineNo := 0;//TEST ONLY to FAIL with duplicate line no

    until SalesQuoteLine.Next() = 0;
    end;
    end;

    }
Sign In or Register to comment.