creating an Item Journal Line via code failed !!

dlauwers
dlauwers Member Posts: 127
Dear mibuso guy's,

I am trying to create a Item Journal Line in code to be able to create a negative or positieve adjustment in code. I need this to clear some test bin's every X time. The items in the test bin's are set to 0 by doing a negative adjustment to the stock.

I can do this manualy by using the item Journal, fill in the fields and lookup the quantity and post the lines.

I also simulated the manuel entry in code. When I run my code, the Item Journal Line table is filled correctly and I can do a post.

But #-o I would like to post line by line NOT using the Journal Line table itself but by pasing a record variable to a codeunit that wil do a negative or positive adjustment with the data that is given with that Item Journal Line Record variable.

This does not have any effect. I debugged and my item journal Line record has the same fields as the journal Line when I fill in the fields manuely via the Item Journal form. I even called to test things the same codeunit that the Item Journal form (form 40) is calling, but this has no effect. There is nothing to post.

When I try other codeunits (22) to post my line, I get an error there a tablelock is already in place ?

I use a report to walk over the records of the selected bin's that need to be emptied and build the Item Journal Line record.

What am I doing wrong !! ](*,) this cannot be that difficult not ? :cry:

This is my code in the report trigger. Item per item in a bin is retrieved and get a negative adjustment for its quantity in that bin.
[b]ITEM ONAFTERGETRECORD[/b]
"Bin Content".CALCFIELDS("Bin Content".Quantity);

itemJline.init;
itemJline.validate("Journal Template Name",'ARTIKEL');
itemJline.validate("Journal Batch Name",'standaard');
itemJline.validate("Posting Date",TODAY);

itemJline.SetUpNewLine(itemJline);

if "Document No." = '' then
begin
  "Document No." := itemJline."Document No.";
end
else
begin
  itemJline.validate("Document No.","Document No.");
end;

counter := counter + 10000;
itemJline.validate("Line No.",counter);
itemJLine.validate("Source Code",'ARTDAGB');
itemJLine.validate("Document Date",Today);
itemJline.VALIDATE("Entry Type",itemJline."Entry Type"::"Negative Adjmt.");
itemJline.VALIDATE("Item No.",Item."No.");
itemJline.validate("Location Code","Bin Content"."Location Code");
itemJline.validate("Bin Code","Bin Content"."Bin Code");
itemJline.VALIDATE(Quantity,"Bin Content".Quantity);
//itemJLine.INSERT;

// Do the correction, call codeunit 22
PostLine.Run(itemJline);  //--> Gives error, cannot run because there is already a table been written or locked...


[-o<
Hope you can help me with this. I need this kind of adjustment also for other movements of items.

Thanks !
Danny

Comments

  • remco_rausch
    remco_rausch Member Posts: 68
    You might want to try
    CLEAR(PostLine);
    PostLine.RUN(itemJLine);
  • ara3n
    ara3n Member Posts: 9,258
    Also if you are not inserted the item journal, leave the line no = 0;
    Leave the Batch and Template blank as well.

    Also clear the ItemJnlLine

    clear(itemJnlLine);
    Ahmed Rashed Amini
    Independent Consultant/Developer


    blog: https://dynamicsuser.net/nav/b/ara3n
  • dlauwers
    dlauwers Member Posts: 127
    Thanks for your replies !

    I got it a bit more working, it seems that my first part of my code to init the newline was conflicting with the codeunit 22. :?

    The following code will reduce the inventory with the total in the bin.
    "Bin Content".CALCFIELDS("Bin Content".Quantity);
    
    if("Bin Content".Quantity>0) then
    begin
      itemJline.init;
      itemJline.validate("Posting Date",TODAY);
      itemJline.validate("Document No.",'BC'+format(today)+ '' + format(Time));
    
      //itemJline.validate("Unit of Measure code","Base Unit of Measure");
      itemJLine.validate("Source Code",'ARTDAGB');
      itemJLine.validate("Document Date",Today);
      itemJline.VALIDATE("Entry Type",itemJline."Entry Type"::"Negative Adjmt.");
      itemJline.VALIDATE("Item No.",Item."No.");
      itemJline.validate("Location Code","Bin Content"."Location Code");
      itemJline.validate("Bin Code","Bin Content"."Bin Code");
      itemJline.VALIDATE(Quantity,"Bin Content".Quantity);
    
      // Do the correction, call codeunit 22
      CLEAR(PostLine);
      PostLine.Run(itemJline);
    end
    else
    begin
      currreport.skip;
    end
    

    BUT !! It will not clear the quantity in the bin itself. That number will remain the same. Only the general inventory is reduced. I can see the post in the item ledger entry table. :(

    How to I specify the correct bin ? Do I have to use another codeunit ?

    Thanks
    Danny
  • ara3n
    ara3n Member Posts: 9,258
    are you using warehouse management? and what version are you on?

    If you are using warehouse management, you need to create warehouse journal.
    Ahmed Rashed Amini
    Independent Consultant/Developer


    blog: https://dynamicsuser.net/nav/b/ara3n
  • dlauwers
    dlauwers Member Posts: 127
    I am on Navision 4 sp3. :wink:

    I am not using warehouse management module, only bin's no zones (not supported by customers lic.)

    I've looked at the table 7312 Warehouse entry and indeed this seems to be the table I was looking for.

    So I probably need to create a warehouse entry line instead of a item journal line.

    Any idea what code unit is needed to do a negative correction (like Codeunit 22 but then for warehouse entry) ?

    I'll try some stuff... :-k

    Danny
  • ara3n
    ara3n Member Posts: 9,258
    How is Location setup? Just bin mandatory is checked?
    The journal line with the bin code should lower the qty in bin content. Are you sure you are using the same unit of measure? What about variant?
    Ahmed Rashed Amini
    Independent Consultant/Developer


    blog: https://dynamicsuser.net/nav/b/ara3n
  • dlauwers
    dlauwers Member Posts: 127
    Hi ara3n,

    The location (location and bin) is copied to the Item journal line as you can see in the code. But I have trouble in setting the unit of measure of the Item journal Line from the item itself. It gives an error (Item of Unit measure does not exists).

    When I skip the unit of measure, the code runs but the bin quantity is not lowered, instead the normal (not warehouse) quantity is lowered.

    Any idea what would cause this ? I feel I'am close to solving this... 8-[
    It seems logical the the unit of measure must be provided, only do I need to find out how the fill it in ?

    I cleared all the special bins manually and added 1 item to the bin. This item has 'Pieces' defined on item card and in Bin Contents I see that this bin stores 'Pieces'.

    I do not use variants.

    mheu ? How do we solve the remaining problem ](*,)
    maybe it will come tomorrow ? I realy hope so !
  • ara3n
    ara3n Member Posts: 9,258
    Make sure for that item. Item unit of measure exists. Go to the item card do a lookup on Base unit of measure. You should see a record in there for pieces. If not insert it and it should solve your error.
    Ahmed Rashed Amini
    Independent Consultant/Developer


    blog: https://dynamicsuser.net/nav/b/ara3n
  • Mbad
    Mbad Member Posts: 344
    When you post without inserting, it is your responsability that the data is correct. You should do like standard(ex. CU 80), and that means use the runwithcheck.
    When programming you really should create code that works in all cases and you wont get dimensions posted using the code you wrote.
  • lubost
    lubost Member Posts: 633
    You can see the shape of filling Item journal line in codeunit 5895 - find RunWithCheck.
  • Mbad
    Mbad Member Posts: 344
    lubost wrote:
    You can see the shape of filling Item journal line in codeunit 5895 - find RunWithCheck.

    Yup that is easier to use, especially if you have a ledger entry.
  • dlauwers
    dlauwers Member Posts: 127
    OK, I understand that it is dangerous to just dump in some lines into a table. I have taken a look at CodeUnit 5895.

    When I fill in de ItemJnkLine a can call Codeunit 22 RunwithCheck function, but this function only does the global inventory, not the bin's.

    I have a working solution where I have created a batch called "system" and under this batch I insert the records needed and then call Codeunit 23 Run to do the processing. This works, but this is an automated simulation of manual entering the data. I would like to have something like in codeunit 5895 where I build an ItemJnlLine and call a RunWithCheck function, but the codeunit 23 does not have that function.

    Or do I need to do 2 posts in my code, One in the Item Journal Line and the second in the warehouse Journal line.

    Maybe I can copy/paste from Codeunit 23 and change that to do my post without the need to insert a line into the table ?

    Any comments ? :-k

    Danny
  • kine
    kine Member Posts: 12,562
    dlauwers wrote:
    When I fill in de ItemJnkLine a can call Codeunit 22 RunwithCheck function, but this function only does the global inventory, not the bin's.

    It is not true. CU 22 is doing all what you need. The problem is somewhere else.
    Kamil Sacek
    MVP - Dynamics NAV
    My BLOG
    NAVERTICA a.s.
  • dlauwers
    dlauwers Member Posts: 127
    Kine,

    Any idea where I went wrong.

    I fill in the Item Journal Line and call codeunit 22 RunwithCheck !

    Could you give me some points I could check ?

    Is it a problem that this run's in a report instead of a codeunit ?

    Hope you can help a bit, because I am stuck at the moment... :?

    Thanks
    Danny
  • kine
    kine Member Posts: 12,562
    For transfering items between bins and locations I am using code like this:
    JnlLine.INIT;
    JnlLine."Journal Template Name" := '';
    JnlLine."Journal Batch Name" := '';
    JnlLine."Document No." := DocNo;
    JnlLine."Line No." := 0;
    JnlLine.VALIDATE("Item No.",ItemNo);
    JnlLine.VALIDATE("Variant Code",VariantCode);
    JnlLine.VALIDATE("Posting Date",WORKDATE);
    JnlLine.VALIDATE("Entry Type",JnlLine."Entry Type"::Transfer);
    JnlLine.VALIDATE("Location Code",FromLoc);
    JnlLine.VALIDATE("Bin Code",FromBin);
    JnlLine.VALIDATE("Unit of Measure Code",UOM);
    JnlLine.VALIDATE(Quantity,Quantity);
    JnlLine.VALIDATE("New Location Code",ToLoc);
    JnlLine.VALIDATE("Source Code",SourceCode);
    JnlLine.VALIDATE("New Bin Code",ToBin);
    JnlLine.VALIDATE(Description,Descr);
    ...  //fillig other needed fields, changing posting groups etc.
    
    PostItemJnl.RUN(JnlLine);
    

    You can add the code for filling temporary dimension table and passing it into RunWithCheck function for posting with dimensions. This code is simplified!
    Kamil Sacek
    MVP - Dynamics NAV
    My BLOG
    NAVERTICA a.s.
  • dlauwers
    dlauwers Member Posts: 127
    Hi Kine,

    I entered the following test code into a codeunit and ran it for testing.
      JnlLine.INIT;
      JnlLine."Journal Template Name" := '';
      JnlLine."Journal Batch Name" := '';
      JnlLine."Document No." := 'Test 001';
      JnlLine."Line No." := 0;
      JnlLine.VALIDATE("Item No.",'ITM-005-000');               // existing item
      JnlLine.VALIDATE("Variant Code",'');                            // Code is blank
      JnlLine.VALIDATE("Posting Date",WORKDATE);
      JnlLine.VALIDATE("Entry Type",JnlLine."Entry Type"::Transfer);
      JnlLine.VALIDATE("Location Code",'ANTW');              // existing Location
      JnlLine.VALIDATE("Bin Code",'LOC1');                   // existing Bin
      JnlLine.VALIDATE("Unit of Measure Code",'STUKS');
      JnlLine.VALIDATE(Quantity,1);                             // We try to move 1
      JnlLine.VALIDATE("New Location Code",'ANTW');
      JnlLine.VALIDATE("Source Code",'ARTDAGB');                // existing source code
      JnlLine.VALIDATE("New Bin Code",'LOC2');                   // existing Bin
      JnlLine.VALIDATE(Description,'Test');
    
       //fillig other needed fields, changing posting groups etc.
       // ...
    
      PostItemJnl.RUN(JnlLine);                                 // run code unit 22
    
      // later fill in the dim's and use runwithcheck
    

    This is doing nothing ](*,)

    When I change the transfer to neg adjustment the overall inventory is decreased by 1, but the bin content is still 100 !!

    The code seems to be moving from global inventory to global inventory, so actualy doing nothing ?

    Very very strange :cry:

    When I compare the code that is run during a manual transfer with the code transfer it is identical for Code Unit 22 !!
    But in the manual transfer more codeunits are called including 7301 Whse. Jnl.-Register Line.

    I checked the code of 7301 and its updating Tabel 7311 and 7312 and if I look in 7312 I found the posted transfers of my manual test. But if I run the code, nothing appears in this table.

    Could you see what code (via code coverage) is run when you run your code to transfer an item from one bin to another ?

    This is the coverage when I run the code...

    Object Type Object ID Object Name Coverage Ratio
    Table 83 Item Journal Line 0,24
    Form 565 Code Coverage 0,74
    Codeunit 22 Item Jnl.-Post Line 0,03
    Codeunit 408 DimensionManagement 0,02
    Codeunit 5402 Unit of Measure Management 0,57
    Codeunit 6500 Item Tracking Management 0,02
    Codeunit 7010 Purch. Price Calc. Mgt. 0,22
    Codeunit 7302 WMS Management 0,01
    Codeunit 50030 Test Code 1,00
    Codeunit 99000815 Reservation-Check Date Confl. 0,03
    Codeunit 99000831 Reservation Engine Mgt. 0,01
    Codeunit 99000835 Item Jnl. Line-Reserve 0,08


    When I do a manual transfer (or neg adjustment) I get the following list...

    Object Type Object ID Object Name Coverage Ratio
    Table 83 Item Journal Line 0,05
    Table 309 No. Series Line 0,09
    Form 393 Item Reclass. Journal 0,13
    Form 565 Code Coverage 0,71
    Codeunit 21 Item Jnl.-Check Line 0,44
    Codeunit 22 Item Jnl.-Post Line 0,03
    Codeunit 23 Item Jnl.-Post Batch 0,50
    Codeunit 240 ItemJnlManagement 0,04
    Codeunit 241 Item Jnl.-Post 0,87
    Codeunit 396 NoSeriesManagement 0,23
    Codeunit 408 DimensionManagement 0,04
    Codeunit 410 Update Analysis View 0,02
    Codeunit 5775 Whse. Management 0,21
    Codeunit 6500 Item Tracking Management 0,03
    Codeunit 7150 Update Item Analysis View 0,02
    Codeunit 7301 Whse. Jnl.-Register Line 0,51
    Codeunit 7302 WMS Management 0,11


    It seems that not only Codeunit 22 is run ?? :-s

    I am going to try to create a Whse. Journal Line and register that also, to see if that produces the correct result. #-o

    Please advice and comment so I can solve this problem and move on with my project.

    Thanks
    Danny
  • Mbad
    Mbad Member Posts: 344
    Did you read what Kines code was for?
    And ofcourse you dont get the same codecoverage, since you dont post dimensions and dont run check.
    Use runwithcheck.
  • dlauwers
    dlauwers Member Posts: 127
    I tried to
    Step 1) Create a Item Journal Line and posted it with CU 22 runWithCheck
    Step 2) Create a warehouse journal Line and used CU 7301 to register it.

    Result was that I can move items between bin's or do a negative or positive adjustment to bin's from code.

    With CU 22 alone, this does not happen. I checked code in CU 80 where a sale was made and I found that if a location is Bin madatory an extra piece of code was called where a warehouse journal line was created and posted.

    I used pieces of code from CU 80, CU 23 and CU 5895 to piece together the needed code to perform the actions.

    I need to check to see if my dimensions are correctly posted, probably need to add some extra code lines to do this. But I spotted them also in the CU mentioned above.

    Do you guy's think of other stuff I need to take into considuration, like dimensions ? Any other fields ?

    Basic line is that the inventory and Bin's are adjusted so I'am gladd :D I got this working.

    Thank to you all to get me this far... \:D/
    Danny

    P.S. I'll put SOLVED in my title next week :-$
  • dlauwers
    dlauwers Member Posts: 127
    The above functionality works, but I still have troubels when I want to move or do a neg/pos adjustment for a specific serial number.

    Has anybody some tips on how to deal with serialnumbers in this case ?

    Code unit 22 generates an error that it does not have any tracking specifications ?

    Thanks
    Danny
  • Mbad
    Mbad Member Posts: 344
    Sounds good that you solved most of the riddle. About the tracking specification, if i remember correctly there is some code in CU 22 that you can check, to find out how to solve the tracking issue(it's to early in the morning for me to check it for ya). Atleast it should give you an idea as to what you need to fill out(the function is usually called something like collectitemtracking). Be carefull about the split line functions.
  • dlauwers
    dlauwers Member Posts: 127
    Still stuck ](*,) with the serialnumber problem for creating a pos/neg adjustment of an item in a bin with a serialnumber.

    By analysing the code in CU22 I found that it is looking in table 337 to see if some serialnumber info is in that table.

    When I use the the manual Item Tracking on sales/pos. adj on Inventory/... this table is filled with the item(s) serial number(s) information that is selected for a certain line.

    I guess I have to also fill in this table with certain info about the item and serialnumber that I want to manipulate (inventory +/-) before I call CU22.

    Can anybody confirm that this is the way to go ? Or do I have to do something else ? :-k

    I hope I can pick your brains about this guy's
    Thanks
    Danny
  • Mbad
    Mbad Member Posts: 344
    dlauwers wrote:
    Can anybody confirm that this is the way to go ? Or do I have to do something else ? :-k

    Your right.

    You will need to try and look at what happens when you manually type in a line, by looking at the tracking lines and reservation entries(important to realize that tracking is also reservation). And yes you will need to create/modify those lines when you create lines via your code(pretty sure filling out the serial no./lot no. isnt enough).
    It requires a few hours of tracking what happens since half of what is going on is coded on the damn form...
  • dlauwers
    dlauwers Member Posts: 127
    I have created the the entries in table 336 to match those that would be entered in this table when you do everything manualy via Item Journal.

    But still I get the same error "Tracking Specification is missing".

    When I use an item with no serial number the +/- adjustment works fine.

    What else can I check ? The code where this error occurs is in CU 22 and is highlited with asterixes *** below
    SplitJnlLine(ItemJnlLine2,PostItemJnlLine)
    IF (ItemJnlLine2."Quantity (Base)" <> 0) AND
       ((ItemJnlLine2."Serial No." <> '') OR (ItemJnlLine2."Lot No." <> ''))
    THEN BEGIN
      IF (ItemJnlLine2."Entry Type" IN
          [ItemJnlLine2."Entry Type"::Verkoop,
           ItemJnlLine2."Entry Type"::"Neg. correctie",
           ItemJnlLine2."Entry Type"::Verbruik]) OR
         ((ItemJnlLine2."Entry Type" = ItemJnlLine2."Entry Type"::Transfer) AND
         NOT PostponeReservationHandling)
      THEN
        SignFactor := -1
      ELSE
        SignFactor := 1;
    
      TempTrackingSpecification.SETRANGE("Serial No.",ItemJnlLine2."Serial No.");
      TempTrackingSpecification.SETRANGE("Lot No.",ItemJnlLine2."Lot No.");
      IF TempTrackingSpecification.FIND('-') THEN BEGIN
        FreeEntryNo := TempTrackingSpecification."Entry No.";
        TempTrackingSpecification.DELETE;
        ItemJnlLine2.TESTFIELD("Serial No.",TempTrackingSpecification."Serial No.");
        ItemJnlLine2.TESTFIELD("Lot No.",TempTrackingSpecification."Lot No.");
        TempTrackingSpecification."Quantity (Base)" := SignFactor * ItemJnlLine2."Quantity (Base)";
        TempTrackingSpecification."Quantity Handled (Base)" := SignFactor * ItemJnlLine2."Quantity (Base)";
        TempTrackingSpecification."Quantity actual Handled (Base)" := SignFactor * ItemJnlLine2."Quantity (Base)";
        TempTrackingSpecification."Quantity Invoiced (Base)" := SignFactor * ItemJnlLine2."Invoiced Qty. (Base)";
        TempTrackingSpecification."Qty. to Invoice (Base)" :=
          SignFactor * (ItemJnlLine2."Quantity (Base)" - ItemJnlLine2."Invoiced Qty. (Base)");
        TempTrackingSpecification."Qty. to Handle (Base)" := 0;
        TempTrackingSpecification."Qty. to Handle" := 0;
        TempTrackingSpecification."Qty. to Invoice" :=
          SignFactor * (ItemJnlLine2.Quantity - ItemJnlLine2."Invoiced Quantity");
        TempTrackingSpecification."Appl.-to Item Entry" := GlobalItemLedgEntry."Entry No.";
        TempTrackingSpecification."Transfer Item Entry No." := TempItemEntryRelation."Item Entry No.";
        IF PostItemJnlLine THEN
          TempTrackingSpecification."Entry No." := TempTrackingSpecification."Appl.-to Item Entry";
        InsertTempTrkgSpecification(FreeEntryNo);
      END ELSE
        IF ItemJnlLine2."Item Charge No." = '' THEN
          IF NOT ItemJnlLine2.Correction THEN // Undo quantity posting.
            ERROR(Text011); ************* <== Error occurs here !
    END;
    
    IF TempSplitItemJnlLine.FIND('-') THEN BEGIN
      JnlLineNo := ItemJnlLine2."Line No.";
      ItemJnlLine2 := TempSplitItemJnlLine;
      ItemJnlLine2."Line No." := JnlLineNo;
      TempSplitItemJnlLine.DELETE;
      EXIT(TRUE);
    END ELSE BEGIN
      IF ItemJnlLine."Phys. Inventory" THEN
        InsertPhysInventoryEntry;
      EXIT(FALSE);
    END
    CollectTrackingSpecification(TargetTrackingSpecification)
    TempTrackingSpecification.RESET;
    TargetTrackingSpecification.RESET;
    TargetTrackingSpecification.DELETEALL;
    
    IF NOT TempTrackingSpecification.FIND('-') THEN
      EXIT(FALSE)
    ELSE
      REPEAT
        TargetTrackingSpecification := TempTrackingSpecification;
        TargetTrackingSpecification.INSERT;
      UNTIL TempTrackingSpecification.NEXT = 0;
    
    TempTrackingSpecification.DELETEALL;
    
    EXIT(TRUE);
    

    The problem is with the TempTrackingSpecification that is empty, I cannot find the code where it is filled in, and because it is a temporary table ? How can I enter something in it from my code ? I don't think that is possible or needed.
    So why is TempTrackingSpecification empty ?

    Any extra info is welcome, this is becomming a time eater :evil:

    I'am close, but not yet there :-k

    Thanks
    Danny