Posting to G/L from Code

anil_mujagicanil_mujagic Member Posts: 91
Hi,

After two days of searching and reading posts on this forum I'm still confused about posting to G/L from code.

I have a codeunit that inserts values in two new fields in Value Entry table (don't ask anything about this Value Entry extension, I just had to do that). When I insert the values I want to post this change in G/L.

For example:
FieldOne has value 1
FieldTwo has value 2

Then I round those two values, to avoid rounding problems, and post this to G/L:
Account 132 Debit amount = 3 (2 + 1)
Account 137 Credit amount = 2
Account 138 Credit amount = 1

I run this code three times:
recGenJnlLine.INIT;
recGenJnlLine.VALIDATE("Journal Template Name", 'GL');
recGenJnlLine.VALIDATE("Journal Batch Name", 'DEFAULT');
recGenJnlLine.VALIDATE("Line No.", 10000 * (recGenJnlLine.COUNT + 1));
recGenJnlLine.VALIDATE("Posting Date", recValueEntry."Posting Date");
recGenJnlLine.VALIDATE("Document Date", recValueEntry."Posting Date");
recGenJnlLine.VALIDATE("Document Type", 0);
recGenJnlLine.VALIDATE("Document No.", recValueEntry."Document No.");
recGenJnlLine.VALIDATE("Account Type", recGenJnlLine."Account Type"::"G/L Account");
recGenJnlLine.VALIDATE("Account No.", cdAccountNo);
recGenJnlLine.VALIDATE(Description, recValueEntry.Description);

IF bDebit THEN
  recGenJnlLine.VALIDATE("Debit Amount", decAmount)
ELSE
  recGenJnlLine.VALIDATE("Credit Amount", decAmount);

recGenJnlLine.VALIDATE("Shortcut Dimension 1 Code", recValueEntry."Global Dimension 1 Code");
recGenJnlLine.VALIDATE("Shortcut Dimension 2 Code", recValueEntry."Global Dimension 2 Code");
  
CLEAR(recGenJnlLine."Gen. Posting Type");
CLEAR(recGenJnlLine."Gen. Bus. Posting Group");
CLEAR(recGenJnlLine."Gen. Prod. Posting Group");

recGenJnlLine.insert(true);

After that I run:
CODEUNIT.RUN(CODEUNIT::"Gen. Jnl.-Post Batch", recGenJnlLine);

Although recGenJnlLine is a Temporary record, I still must take care of
"Journal Template Name" and "Journal Batch Name" and I want to avoid that.

So I tried this (got it from Codeunit 80 and changed line with "Table ID"):
recTempJnlLineDim.DELETEALL;
recTempDocDim.RESET;
recTempDocDim.SETRANGE("Table ID", DATABASE::"Value Entry");
cuDimMgt.CopyDocDimToJnlLineDim(recTempDocDim, recTempJnlLineDim);
cuPostGenJnlLine.RunWithCheck(recGenJnlLine, recTempJnlLineDim);

and I get some G/L Entry CONSISTENCY ERROR. I don't know why?! I tried to make the recGenJnlLine nontemporary and actually insert lines to gen journal line table, and when I open that journal balance is ok (0).

So, what is the correct way to post Gen. Journal Lines without inserting in the database and without "Journal Template Name" and "Journal Batch Name"?

Comments

  • leugimleugim Member Posts: 93
    hi

    if you insert records in a nontemporary Gen. Journal Line and then check these records, in fact you won't see any inconsistency and the Amount in one record will be the sum of the Amount in the other two records. but posting these records, NAV possibly uses more decimals you can see, so there could be the inconsistency. in standar ES versions, Unit-Amount Rounding Precision is set to 0,00001 and Amount Rounding Precision is set to 0,01... take a look at g/l setup. there you can set the number of decimals NAV must adjust to

    i see you use VALIDATE sentences so hard. i prefer to use VALIDATE only when i need to execute some standar code to retrieve data. if you use VALIDATE(AMOUNT), you can forget that annoying IF you use to know if Amount is positive or negative... please take a look at code inside tbl 81, you will find NAV can work for you most of the time, saving a big amount of time... \:D/

    hope this could be helpful
    _______________
    so far, so good
  • anil_mujagicanil_mujagic Member Posts: 91
    leugim wrote:
    hi

    if you insert records in a nontemporary Gen. Journal Line and then check these records, in fact you won't see any inconsistency and the Amount in one record will be the sum of the Amount in the other two records. but posting these records, NAV possibly uses more decimals you can see, so there could be the inconsistency. in standar ES versions, Unit-Amount Rounding Precision is set to 0,00001 and Amount Rounding Precision is set to 0,01... take a look at g/l setup. there you can set the number of decimals NAV must adjust to

    As I said, I round values before inserting in Gen. Jnl Line, and in this case (test data) I even have whole numbers: 1 + 2 = 3

    leugim wrote:
    i see you use VALIDATE sentences so hard. i prefer to use VALIDATE only when i need to execute some standar code to retrieve data.

    that is exactly what I want to achieve - to make navision populate everything it needs trough it's validate trigers, so I don't need to do unnecessary assignments on bunch of fields.

    leugim wrote:
    if you use VALIDATE(AMOUNT), you can forget that annoying IF you use to know if Amount is positive or negative... please take a look at code inside tbl 81, you will find NAV can work for you most of the time, saving a big amount of time... \:D/

    Validate Amount is there because it populates all necessary amount fields.

    "annoying IF" is there because i will have cases when I need to post a negative amount as a debit amount (reversal posting)
    leugim wrote:
    hope this could be helpful

    Thanks anyway! :wink:
  • anil_mujagicanil_mujagic Member Posts: 91
    Can someone give an example of working code that posts to GL using RunWithCheck procedure?
  • WiechardtWiechardt Member Posts: 25
    Hi

    You don't need to use a temporary variable and you don't need to insert the record either...take a look at codeunit 80 or 90...in this codeunit the systems posts to the G/L in many instances to post customer entries, etc.

    Notice from the code below (taken from Codeunit 80 - post customer entry) that:
    1. It's not a temp variable that is being used
    2. The code does not actually insert the GenJnlLine record prior to calling the RunWithCheck routine - this is to ensure that it works in a concurrent environment and to avoid unecessary locks.
    3. No validation is done on any of the fields, because when automating the posting to the G/L through code you do not want (potential) confirmation/warning messages to appear halfway through the process. This also means that you will need to know which fields to populate with values and what these values should be - you can use the code below as a guideline.

    GenJnlLine.INIT;
    GenJnlLine."Posting Date" := "Posting Date";
    GenJnlLine."Document Date" := "Document Date";
    GenJnlLine.Description := "Posting Description";
    GenJnlLine."Shortcut Dimension 1 Code" := "Shortcut Dimension 1 Code";
    GenJnlLine."Shortcut Dimension 2 Code" := "Shortcut Dimension 2 Code";
    GenJnlLine."Reason Code" := "Reason Code";
    GenJnlLine."Account Type" := GenJnlLine."Account Type"::Customer;
    GenJnlLine."Account No." := "Bill-to Customer No.";
    GenJnlLine."Document Type" := GenJnlLineDocType;
    GenJnlLine."Document No." := GenJnlLineDocNo;
    GenJnlLine."External Document No." := GenJnlLineExtDocNo;
    GenJnlLine."Currency Code" := "Currency Code";
    GenJnlLine.Amount := -TotalSalesLine."Amount Including VAT";
    GenJnlLine."Source Currency Code" := "Currency Code";
    GenJnlLine."Source Currency Amount" := -TotalSalesLine."Amount Including VAT";
    GenJnlLine."Amount (LCY)" := -TotalSalesLineLCY."Amount Including VAT";
    IF SalesHeader."Currency Code" = '' THEN
    GenJnlLine."Currency Factor" := 1
    ELSE
    GenJnlLine."Currency Factor" := SalesHeader."Currency Factor";
    GenJnlLine.Correction := Correction;
    GenJnlLine."Sales/Purch. (LCY)" := -TotalSalesLineLCY.Amount;
    GenJnlLine."Profit (LCY)" := -(TotalSalesLineLCY.Amount - TotalSalesLineLCY."Unit Cost (LCY)");
    GenJnlLine."Inv. Discount (LCY)" := -TotalSalesLineLCY."Inv. Discount Amount";
    GenJnlLine."Sell-to/Buy-from No." := "Sell-to Customer No.";
    GenJnlLine."Bill-to/Pay-to No." := "Bill-to Customer No.";
    GenJnlLine."Salespers./Purch. Code" := "Salesperson Code";
    GenJnlLine."System-Created Entry" := TRUE;
    GenJnlLine."On Hold" := "On Hold";
    GenJnlLine."Applies-to Doc. Type" := "Applies-to Doc. Type";
    GenJnlLine."Applies-to Doc. No." := "Applies-to Doc. No.";
    GenJnlLine."Applies-to ID" := "Applies-to ID";
    GenJnlLine."Allow Application" := "Bal. Account No." = '';
    GenJnlLine."Due Date" := "Due Date";
    GenJnlLine."Payment Terms Code" := "Payment Terms Code";
    GenJnlLine."Pmt. Discount Date" := "Pmt. Discount Date";
    GenJnlLine."Payment Discount %" := "Payment Discount %";
    GenJnlLine."Source Type" := GenJnlLine."Source Type"::Customer;
    GenJnlLine."Source No." := "Bill-to Customer No.";
    GenJnlLine."Source Code" := SrcCode;
    GenJnlLine."Posting No. Series" := "Posting No. Series";
    GenJnlLine."IC Partner Code" := "Sell-to IC Partner Code";

    TempJnlLineDim.DELETEALL;
    TempDocDim.RESET;
    TempDocDim.SETRANGE("Table ID",DATABASE::"Sales Header");
    DimMgt.CopyDocDimToJnlLineDim(TempDocDim,TempJnlLineDim);
    GenJnlPostLine.RunWithCheck(GenJnlLine,TempJnlLineDim);

    Hope this helps.
  • tinoruijstinoruijs Member Posts: 1,226
    Before you are going to post to G/L from code, maybe you could take a look at the following post, because it can be very tricky:

    http://www.mibuso.com/forum/viewtopic.php?t=7374

    Tino Ruijs
    Microsoft Dynamics NAV specialist
  • anil_mujagicanil_mujagic Member Posts: 91
    Thank you all for your help. I managed to make a function that does posting without errors but I still don't understand why it won't work the way I want???!!! :D

    I was trying to make a function that receives account number and amount (also few other parameters) and does posting to GL. Here is the pseudo code:
    function PostToGL(cdAccountNo, decAmount)
    BEGIN
      recGenJnlLine.INIT;
      recGenJnlLine.VALIDATE("Line No.", 10000 * i);
      recGenJnlLine.VALIDATE("Account No.", cdAccountNo);  
      recGenJnlLine.VALIDATE(Amount, decAmount)
      .
      .
      .
      recTempJnlLineDim.DELETEALL;
      recTempDocDim.RESET;
      recTempDocDim.SETRANGE("Table ID", DATABASE::"Value Entry");
      cuDimMgt.CopyDocDimToJnlLineDim(recTempDocDim, recTempJnlLineDim);
      cuPostGenJnlLine.RunWithCheck(recGenJnlLine, recTempJnlLineDim);
    END
    

    Then I would call that function few times to post lines to GL. But it didn't work (consistency error). Instead I took the code out of that function and put it in loop where I do posting:
    FOR i := 1 TO 3 DO 
    BEGIN
      recGenJnlLine.INIT;
      recGenJnlLine.VALIDATE("Line No.", 10000 * i);
      recGenJnlLine.VALIDATE("Account No.", cdAccountNo[i]);  
      recGenJnlLine.VALIDATE(Amount, decAmount[i])
      .
      .
      .
      recTempJnlLineDim.DELETEALL;
      recTempDocDim.RESET;
      recTempDocDim.SETRANGE("Table ID", DATABASE::"Value Entry");
      cuDimMgt.CopyDocDimToJnlLineDim(recTempDocDim, recTempJnlLineDim);
      cuPostGenJnlLine.RunWithCheck(recGenJnlLine, recTempJnlLineDim);
    END
    

    ...and it works... but, now I have another problem :lol: ...
  • anil_mujagicanil_mujagic Member Posts: 91
    The new problem that I have is the same that this guy had:

    http://www.mibuso.com/forum/viewtopic.php?t=13068&highlight=entry+already+exists

    I have procedure that does aditional posting to GL for every change in item quantity in specific location. So I put this code in Codeunit 22 in RunWithCheck trigger (//RIPLOG01 is my code):
    WHILE SplitJnlLine(ItemJnlLine,PostItemJnlLine) DO
      IF PostItemJnlLine THEN BEGIN
        Code;
        //RIPLOG01 BEGIN
        IF cuRetailInventoryPosting.IsRetailLocation("Location Code") THEN
          cuRetailInventoryPosting.Post("Item No.");
        IF cuRetailInventoryPosting.IsRetailLocation("New Location Code") THEN
          cuRetailInventoryPosting.Post("Item No.");
        //RIPLOG01 END
      END;
    

    But I get the error which says that G/L Entry allready exists. I traced the problem with the debuger and the problem is that after the function Code; finishes it's job, last G/L Entry is (for example) 20015. Then my function posts additional three entries and last G/L Entry is then 20018. After that, when second item is to be posted, it again tries to insert G/L Entry line with number 20015. It looks like it doesn't see my postings.

    Is it possible to solve this problem? I must make the necessary postings in this codeunit because it is called whenever the item is posted. Moving the code into codeunits on "upper" level (Sales Post, Purchase Post, Transfer Post...) is bad solution because I will never be sure that I covered every item posting. And also if I post changes directly from Item Journal, it calls post line codeunit directly, what then?

    Does anyone have an idea? ](*,)
Sign In or Register to comment.