Assign serial numbers to purchase order line

DmitriySozinovDmitriySozinov Member Posts: 23
edited 2022-05-19 in NAV Three Tier
Hi,

Trying to find a proper solution for assigning serial numbers to a purchase order line through extension or API method.
BC version is 19.3.0.2 on-prem.

Here is the extension method code:

7tqv1d9yr3t6.png

0b4rv3dtulwy.png

In NAV, you would pass serial number directly into CreateReservEntry.CreateReservEntryFor method, like this:

0hvpaapiu1tl.png

xao2nfm7l8bg.png


But in BC, CreateReservEntry.CreateReservEntryFor method is changed, so you no longer can pass Serial No., but instead Serial No. is copied from ReservEntry:

Codeunit 99000830 Create Reserv. Entry

0rvspgzsme02.png

Table 337 Reservation Entry

kcp5lxttxpb9.png

So, the question is what would be the correct way to 'feed' Reservation Entry with serial nos. before executing CreateReservEntryFor?

Is there a method in Codeunit 99000830 Create Reserv. Entry or Table 337 Reservation Entry that can be utilized for this?


Best Answer

  • DmitriySozinovDmitriySozinov Member Posts: 23
    Answer ✓
    Hi Developer01 :-)

    So far the code that seems to work, but is still being tested looks like this:
    procedure AssignSerialNos(DocumentType: Integer; DocumentNumber: Code[20]; LineNo: Integer; SerialNosString: Text) Assigned: Boolean;
        var
            Item: Record Item;
            PurchaseHeader: Record "Purchase Header";
            PurchaseLine: Record "Purchase Line";
            ReservationEntry: Record "Reservation Entry";
            TrackingSpecification: Record "Tracking Specification";
            CreateReservEntry: Codeunit "Create Reserv. Entry";
            ItemTrackingMgt: Codeunit "Item Tracking Management";
            ItemTrackingPage: Page "Item Tracking Lines";
            TrackingLinesInitialized: Boolean;
            i: Integer;
            SerialNosList: List of [Text];
            RunMode: Enum "Item Tracking Run Mode";
        begin
            SerialNosList := SerialNosString.Split(';');
            if SerialNosList.Count = 0 then
                exit(false);
    
            PurchaseHeader.Get(DocumentType, DocumentNumber); //DocumentType:Order=1,Invoice=2,CreditNote=3        
            case PurchaseHeader."Document Type" of
                PurchaseHeader."Document Type"::Order:
                    PurchaseLine.Get(PurchaseHeader."Document Type"::Order, PurchaseHeader."No.", LineNo);
                PurchaseHeader."Document Type"::Invoice:
                    PurchaseLine.Get(PurchaseHeader."Document Type"::Invoice, PurchaseHeader."No.", LineNo);
            end;
    
            PurchaseLine.TestField(Type, 2); //2 = item            
            PurchaseLine.TestField("No.");
            PurchaseLine.TestField("Quantity (Base)");
    
            Item.Get(PurchaseLine."No.");
            Item.TestField("Item Tracking Code");
    
            ReservationEntry.Reset();
            ReservationEntry.SetRange("Source Type", DATABASE::"Purchase Line");
            ReservationEntry.SetRange("Source Subtype", PurchaseLine."Document Type");
            ReservationEntry.SetRange("Source ID", PurchaseLine."Document No.");
            ReservationEntry.SetRange("Source Ref. No.", PurchaseLine."Line No.");
            ReservationEntry.SetRange("Source Batch Name", '');
            ReservationEntry.SetRange("Source Prod. Order Line", 0);
            If NOT ReservationEntry.IsEmpty then begin
                ReservationEntry.DeleteAll(true);
            end;
    
            For i := 1 to SerialNosList.Count do begin
                ReservationEntry."Serial No." := SerialNosList.Get(i);
    
                if PurchaseLine."Document Type" = PurchaseLine."Document Type"::Order then begin
                    CreateReservEntry.CreateReservEntryFor(
                        DATABASE::"Purchase Line",   //ForType
                        1,                           //ForSubtype - Order
                        PurchaseLine."Document No.", //ForID
                        '',                          //ForBatchName
                        0,                           //ForProdOrderLine
                        PurchaseLine."Line No.",     //ForProdOrderLine
                        1,                           //ForQtyPerUOM
                        1,                           //Quantity
                        1,                           //QuantityBase
                        ReservationEntry);           //ForReservEntry            
                end;
    
                if PurchaseLine."Document Type" = PurchaseLine."Document Type"::Invoice then begin
                    CreateReservEntry.CreateReservEntryFor(
                        DATABASE::"Purchase Line",   //ForType
                        2,                           //ForSubtype - Invoice
                        PurchaseLine."Document No.", //ForID
                        '',                          //ForBatchName
                        0,                           //ForProdOrderLine
                        PurchaseLine."Line No.",     //ForProdOrderLine
                        1,                           //ForQtyPerUOM
                        1,                           //Quantity
                        1,                           //QuantityBase
                        ReservationEntry);           //ForReservEntry            
                end;
    
                CreateReservEntry.CreateEntry(
                    PurchaseLine."No.",
                    PurchaseLine."Variant Code",
                    PurchaseLine."Location Code",
                    PurchaseLine.Description,
                    PurchaseLine."Expected Receipt Date",
                    0D,
                    0,
                    ReservationEntry."Reservation Status"::Surplus);
    
                // item tracking lines have to be synchronized between sales and purchase orders, when the purchase order is a drop shipment
                If PurchaseLine."Drop Shipment" then begin
                    If not TrackingLinesInitialized then begin
                        //PurchLineReserve.InitTrackingSpecification(PurchaseLineLoc,TrackingSpecification);
                        TrackingSpecification.InitFromPurchLine(PurchaseLine);
                        ItemTrackingPage.SetRunMode(Runmode::"Drop Shipment");
                        IF PurchaseLine."Sales Order No." <> '' THEN
                            ItemTrackingPage.SetSecondSourceRowID(ItemTrackingMgt.ComposeRowID(DATABASE::"Sales Line", 1, PurchaseLine."Sales Order No.", '', 0, PurchaseLine."Sales Order Line No."));
                        ItemTrackingPage.SetSourceSpec(TrackingSpecification, PurchaseLine."Expected Receipt Date");
                        TrackingLinesInitialized := true;
                    end;
                    ItemTrackingPage.SynchronizeLinkedSources('')
                end;
            end;
        end;
    

Answers

  • Developer101Developer101 Member Posts: 542
    As you loop you could assign serial no. to a reservation entry table instance before executing createreserventryfor function ?
    United Kingdom
  • DmitriySozinovDmitriySozinov Member Posts: 23
    Thank you, sounds like an obvious solution :) I will give it a try.
  • Developer101Developer101 Member Posts: 542
    Thank you. Let me know how it goes :)
    United Kingdom
  • DmitriySozinovDmitriySozinov Member Posts: 23
    Answer ✓
    Hi Developer01 :-)

    So far the code that seems to work, but is still being tested looks like this:
    procedure AssignSerialNos(DocumentType: Integer; DocumentNumber: Code[20]; LineNo: Integer; SerialNosString: Text) Assigned: Boolean;
        var
            Item: Record Item;
            PurchaseHeader: Record "Purchase Header";
            PurchaseLine: Record "Purchase Line";
            ReservationEntry: Record "Reservation Entry";
            TrackingSpecification: Record "Tracking Specification";
            CreateReservEntry: Codeunit "Create Reserv. Entry";
            ItemTrackingMgt: Codeunit "Item Tracking Management";
            ItemTrackingPage: Page "Item Tracking Lines";
            TrackingLinesInitialized: Boolean;
            i: Integer;
            SerialNosList: List of [Text];
            RunMode: Enum "Item Tracking Run Mode";
        begin
            SerialNosList := SerialNosString.Split(';');
            if SerialNosList.Count = 0 then
                exit(false);
    
            PurchaseHeader.Get(DocumentType, DocumentNumber); //DocumentType:Order=1,Invoice=2,CreditNote=3        
            case PurchaseHeader."Document Type" of
                PurchaseHeader."Document Type"::Order:
                    PurchaseLine.Get(PurchaseHeader."Document Type"::Order, PurchaseHeader."No.", LineNo);
                PurchaseHeader."Document Type"::Invoice:
                    PurchaseLine.Get(PurchaseHeader."Document Type"::Invoice, PurchaseHeader."No.", LineNo);
            end;
    
            PurchaseLine.TestField(Type, 2); //2 = item            
            PurchaseLine.TestField("No.");
            PurchaseLine.TestField("Quantity (Base)");
    
            Item.Get(PurchaseLine."No.");
            Item.TestField("Item Tracking Code");
    
            ReservationEntry.Reset();
            ReservationEntry.SetRange("Source Type", DATABASE::"Purchase Line");
            ReservationEntry.SetRange("Source Subtype", PurchaseLine."Document Type");
            ReservationEntry.SetRange("Source ID", PurchaseLine."Document No.");
            ReservationEntry.SetRange("Source Ref. No.", PurchaseLine."Line No.");
            ReservationEntry.SetRange("Source Batch Name", '');
            ReservationEntry.SetRange("Source Prod. Order Line", 0);
            If NOT ReservationEntry.IsEmpty then begin
                ReservationEntry.DeleteAll(true);
            end;
    
            For i := 1 to SerialNosList.Count do begin
                ReservationEntry."Serial No." := SerialNosList.Get(i);
    
                if PurchaseLine."Document Type" = PurchaseLine."Document Type"::Order then begin
                    CreateReservEntry.CreateReservEntryFor(
                        DATABASE::"Purchase Line",   //ForType
                        1,                           //ForSubtype - Order
                        PurchaseLine."Document No.", //ForID
                        '',                          //ForBatchName
                        0,                           //ForProdOrderLine
                        PurchaseLine."Line No.",     //ForProdOrderLine
                        1,                           //ForQtyPerUOM
                        1,                           //Quantity
                        1,                           //QuantityBase
                        ReservationEntry);           //ForReservEntry            
                end;
    
                if PurchaseLine."Document Type" = PurchaseLine."Document Type"::Invoice then begin
                    CreateReservEntry.CreateReservEntryFor(
                        DATABASE::"Purchase Line",   //ForType
                        2,                           //ForSubtype - Invoice
                        PurchaseLine."Document No.", //ForID
                        '',                          //ForBatchName
                        0,                           //ForProdOrderLine
                        PurchaseLine."Line No.",     //ForProdOrderLine
                        1,                           //ForQtyPerUOM
                        1,                           //Quantity
                        1,                           //QuantityBase
                        ReservationEntry);           //ForReservEntry            
                end;
    
                CreateReservEntry.CreateEntry(
                    PurchaseLine."No.",
                    PurchaseLine."Variant Code",
                    PurchaseLine."Location Code",
                    PurchaseLine.Description,
                    PurchaseLine."Expected Receipt Date",
                    0D,
                    0,
                    ReservationEntry."Reservation Status"::Surplus);
    
                // item tracking lines have to be synchronized between sales and purchase orders, when the purchase order is a drop shipment
                If PurchaseLine."Drop Shipment" then begin
                    If not TrackingLinesInitialized then begin
                        //PurchLineReserve.InitTrackingSpecification(PurchaseLineLoc,TrackingSpecification);
                        TrackingSpecification.InitFromPurchLine(PurchaseLine);
                        ItemTrackingPage.SetRunMode(Runmode::"Drop Shipment");
                        IF PurchaseLine."Sales Order No." <> '' THEN
                            ItemTrackingPage.SetSecondSourceRowID(ItemTrackingMgt.ComposeRowID(DATABASE::"Sales Line", 1, PurchaseLine."Sales Order No.", '', 0, PurchaseLine."Sales Order Line No."));
                        ItemTrackingPage.SetSourceSpec(TrackingSpecification, PurchaseLine."Expected Receipt Date");
                        TrackingLinesInitialized := true;
                    end;
                    ItemTrackingPage.SynchronizeLinkedSources('')
                end;
            end;
        end;
    
Sign In or Register to comment.