Skip to main content

Notifications

Announcements

No record found.

Microsoft Dynamics NAV (Archived)

Apply vendor ledger entries foreign currency not creating realized gain/loss

Posted on by Microsoft Employee

Hello, 

While developing a customization for vendor ledger entries application I came across a weird NAV behavior. I will expose the example for a better understanding:

1st step) Post purchase invoice in foreign currency (posting date 05-21-2018):  Amount 3000 GBP (foreign currency) and Amount LCY 2000 (currency exchange rate = 1.5). 

2nd step) Exchange Rate Adjustment (posting date 05-31-2018): Unrealized Gain of 235.29 (currency exchange rate = 1.7).

3rd step) Post payment in LCY through payment journal (posting date 06-15-2018): Amount LCY 2,142.86 (currency exchange rate = 1.4).

4th step) Vendor ledger entries application (posting date 06-15-2018). I tried two cases:

  A) Selecting the payment entry and then the action "Apply Entries". Afterwards I select the invoice (Set Applies-to ID) and post the application. Here, the unrealized amount is correctly posted with opposite sign to settle the unrealized account (-235.29) and then the realized loss is posted (-142.86). In this case, both entries are closed.

  B) Selecting the invoice entry and then the action "Apply Entries". Afterwards I select the payment (Set Applies-to ID) and post the application. Here, the unrealized amount is correctly posted with opposite sign to settle the unrealized account (-235.29) but no realized loss is posted. In this case, only the invoice entry is closed, because the application converts the payment amount in LCY (2,142.86) to foreign currency (3,214.29 GBP) using the exchange rate of the invoice posting date (05-21-2018).

Could it be a bug from standard NAV? I do not see a functional explanation for behavior of case B. I would really appreciate any help given.

*This post is locked for comments

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: Apply vendor ledger entries foreign currency not creating realized gain/loss

    The NAV is different and the calculations done by this application is also different. Everyone knows how to connect to router support for solving the currency calculation problems.

  • Jens Glathe Profile Picture
    Jens Glathe 6,092 on at
    RE: Apply vendor ledger entries foreign currency not creating realized gain/loss

    Hi there,

    an update to this: I think the common sense logic (and my colleagues from banking) says that there is more errors in this. For mixed currency application, there should be two rules:

    1. If it is on the same point in time, it's an exchange deal. Use the rates given in the original entries for the application. No gains/losses are calculated. For a non FX trading system like NAV is, "same point in time" is the same posting date.

    2. If it is an application with a time span, calculate gains/losses between the original currency factors of applying (later) and applied entry. Since the currency factor is always with respect to the local currency of the company, it is sufficient data for application between any combinations of currency anyway, but not for calculation of gain/loss in the mixed currency case. For this, all applied entries must be recalculated against the applying entry. Not all combinations can have realized gains/losses, though. Basically it is the case when an invoice is in currency, than you can have gains/losses, regardless of the payment currency - it is always calculated against the original exchange rate. The exception is when all applied entries are in local currency. In this case it can be considered as an exchange deal, too, and there shouldn't be any gains or losses.

    I am pretty sure that NAV doesn't work this way. Case A) seems to be right (invoice in currency, payment in LCY),  case B) should have the exchange rate of the payment entry date as base for the gains/losses. And should basically post the same as case A). The above rules are not implemented, though.

    I think I'll take a stab at this... mixed currency application is more common than one expects.

    with best regards

    Jens

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: Apply vendor ledger entries foreign currency not creating realized gain/loss

    Hi Jens,

    Thank you for your detailed answer. It reassured my suspicions.

    I find it surprising that this has been like this for so many years.

    Now we will consider what step to take next.

    Kind regards,

    Laura

  • Verified answer
    Jens Glathe Profile Picture
    Jens Glathe 6,092 on at
    RE: Apply vendor ledger entries foreign currency not creating realized gain/loss

    Hi Laura,

    out of curiosity I took a look into an AddOn that also handles applications extensively (gbedv OP-Plus), and yes, they also consider this a bug, as it seems. They change this behaviour by flag.

    with best regards

    Jens

  • Verified answer
    Jens Glathe Profile Picture
    Jens Glathe 6,092 on at
    RE: Apply vendor ledger entries foreign currency not creating realized gain/loss

    Hi Laura,

    I would call it a bug. In earlier versions of NAV you could give an application date for the application transaction, I think this is now completely eliminated. Now the applying date will be derived from the entries to apply. It is either the newest date of the two (or so) entries participating in the application transaction (Applies-to doc no.), or the newest entry date of entries to apply (Applies-to ID). So, it should be the latest posting date to be found in the participating entries.

    For case B, all entries of the application pool will be converted to GBP at application date (latest posting date) using the currency exchange rates table. If the conversion takes place to a different date, it would be wrong, IMO. However, a research in the repositories has shown that the offending code is there since NAV2013R2 RTM: 

    (CodeUnit 12)

    LOCAL PROCEDURE PrepareTempVendLedgEntry@119(GenJnlLine@1004 : Record 81;VAR NewCVLedgEntryBuf@1003 : Record 382;VAR TempOldVendLedgEntry@1002 : TEMPORARY Record 25;Vend@1001 : Record 23;VAR ApplyingDate@1000 : Date) : Boolean; VAR OldVendLedgEntry@1018 : Record 25; PurchSetup@1013 : Record 312; GenJnlApply@1012 : Codeunit 225; RemainingAmount@1009 : Decimal; BEGIN IF GenJnlLine."Applies-to Doc. No." <> '' THEN BEGIN // Find the entry to be applied to OldVendLedgEntry.RESET; OldVendLedgEntry.SETCURRENTKEY("Document No."); OldVendLedgEntry.SETRANGE("Document No.",GenJnlLine."Applies-to Doc. No."); OldVendLedgEntry.SETRANGE("Document Type",GenJnlLine."Applies-to Doc. Type"); OldVendLedgEntry.SETRANGE("Vendor No.",NewCVLedgEntryBuf."CV No."); OldVendLedgEntry.SETRANGE(Open,TRUE); OldVendLedgEntry.FINDFIRST; OldVendLedgEntry.TESTFIELD(Positive,NOT NewCVLedgEntryBuf.Positive); IF OldVendLedgEntry."Posting Date" > ApplyingDate THEN ApplyingDate := OldVendLedgEntry."Posting Date"; GenJnlApply.CheckAgainstApplnCurrency( NewCVLedgEntryBuf."Currency Code",OldVendLedgEntry."Currency Code",GenJnlLine."Account Type"::Vendor,TRUE); TempOldVendLedgEntry := OldVendLedgEntry; TempOldVendLedgEntry.INSERT; END ELSE BEGIN // Find the first old entry (Invoice) which the new entry (Payment) should apply to OldVendLedgEntry.RESET; OldVendLedgEntry.SETCURRENTKEY("Vendor No.","Applies-to ID",Open,Positive,"Due Date"); TempOldVendLedgEntry.SETCURRENTKEY("Vendor No.","Applies-to ID",Open,Positive,"Due Date"); OldVendLedgEntry.SETRANGE("Vendor No.",NewCVLedgEntryBuf."CV No."); OldVendLedgEntry.SETRANGE("Applies-to ID",GenJnlLine."Applies-to ID"); OldVendLedgEntry.SETRANGE(Open,TRUE); OldVendLedgEntry.SETFILTER("Entry No.",'<>%1',NewCVLedgEntryBuf."Entry No."); IF NOT (Vend."Application Method" = Vend."Application Method"::"Apply to Oldest") THEN OldVendLedgEntry.SETFILTER("Amount to Apply",'<>%1',0); IF Vend."Application Method" = Vend."Application Method"::"Apply to Oldest" THEN OldVendLedgEntry.SETFILTER("Posting Date",'..%1',GenJnlLine."Posting Date"); // Check and Move Ledger Entries to Temp PurchSetup.GET; IF PurchSetup."Appln. between Currencies" = PurchSetup."Appln. between Currencies"::None THEN OldVendLedgEntry.SETRANGE("Currency Code",NewCVLedgEntryBuf."Currency Code"); IF OldVendLedgEntry.FINDSET(FALSE,FALSE) THEN REPEAT IF GenJnlApply.CheckAgainstApplnCurrency( NewCVLedgEntryBuf."Currency Code",OldVendLedgEntry."Currency Code",GenJnlLine."Account Type"::Vendor,FALSE) THEN BEGIN IF (OldVendLedgEntry."Posting Date" > ApplyingDate) AND (OldVendLedgEntry."Applies-to ID" <> '') THEN ApplyingDate := OldVendLedgEntry."Posting Date"; TempOldVendLedgEntry := OldVendLedgEntry; TempOldVendLedgEntry.INSERT; END; UNTIL OldVendLedgEntry.NEXT = 0; TempOldVendLedgEntry.SETRANGE(Positive,NewCVLedgEntryBuf."Remaining Amount" > 0); IF TempOldVendLedgEntry.FIND('-') THEN BEGIN RemainingAmount := NewCVLedgEntryBuf."Remaining Amount"; TempOldVendLedgEntry.SETRANGE(Positive); TempOldVendLedgEntry.FIND('-'); REPEAT TempOldVendLedgEntry.CALCFIELDS("Remaining Amount"); TempOldVendLedgEntry.RecalculateAmounts( TempOldVendLedgEntry."Currency Code",NewCVLedgEntryBuf."Currency Code",NewCVLedgEntryBuf."Posting Date"); IF PaymentToleranceMgt.CheckCalcPmtDiscCVVend(NewCVLedgEntryBuf,TempOldVendLedgEntry,0,FALSE,FALSE) THEN TempOldVendLedgEntry."Remaining Amount" -= TempOldVendLedgEntry."Remaining Pmt. Disc. Possible"; RemainingAmount += TempOldVendLedgEntry."Remaining Amount"; UNTIL TempOldVendLedgEntry.NEXT = 0; TempOldVendLedgEntry.SETRANGE(Positive,RemainingAmount < 0); END ELSE TempOldVendLedgEntry.SETRANGE(Positive); EXIT(TempOldVendLedgEntry.FIND('-')); END; EXIT(TRUE); END;

    So... wrong since NAV2013R2? In this code, every single participating entry would be converted at the posting date of the appplying entry (the invoice in case B) , even though the application date might by something entirely different. It is not written into the (temporary) entries, though. Interestingly, the same is done in PostApply():

        LOCAL PROCEDURE PostApply@105(GenJnlLine@1007 : Record 81;VAR DtldCVLedgEntryBuf@1008 : Record 383;VAR OldCVLedgEntryBuf@1000 : Record 382;VAR NewCVLedgEntryBuf@1005 : Record 382;VAR NewCVLedgEntryBuf2@1013 : Record 382;BlockPaymentTolerance@1006 : Boolean;AllApplied@1009 : Boolean;VAR AppliedAmount@1016 : Decimal;VAR PmtTolAmtToBeApplied@1010 : Decimal);
        VAR
          OldCVLedgEntryBuf2@1003 : Record 382;
          OldCVLedgEntryBuf3@1002 : Record 382;
          OldRemainingAmtBeforeAppln@1001 : Decimal;
          ApplnRoundingPrecision@1004 : Decimal;
          AppliedAmountLCY@1012 : Decimal;
          OldAppliedAmount@1011 : Decimal;
        BEGIN
          OldRemainingAmtBeforeAppln := OldCVLedgEntryBuf."Remaining Amount";
          OldCVLedgEntryBuf3 := OldCVLedgEntryBuf;
    
          // Management of posting in multiple currencies
          OldCVLedgEntryBuf2 := OldCVLedgEntryBuf;
          OldCVLedgEntryBuf.COPYFILTER(Positive,OldCVLedgEntryBuf2.Positive);
          ApplnRoundingPrecision := GetApplnRoundPrecision(NewCVLedgEntryBuf,OldCVLedgEntryBuf);
    
          OldCVLedgEntryBuf2.RecalculateAmounts(
            OldCVLedgEntryBuf2."Currency Code",NewCVLedgEntryBuf."Currency Code",NewCVLedgEntryBuf."Posting Date");
    
          IF NOT BlockPaymentTolerance THEN
            CalcPmtTolerance(
              NewCVLedgEntryBuf,OldCVLedgEntryBuf,OldCVLedgEntryBuf2,DtldCVLedgEntryBuf,GenJnlLine,
              PmtTolAmtToBeApplied,NextTransactionNo,FirstNewVATEntryNo);
    
          CalcPmtDisc(
            NewCVLedgEntryBuf,OldCVLedgEntryBuf,OldCVLedgEntryBuf2,DtldCVLedgEntryBuf,GenJnlLine,
            PmtTolAmtToBeApplied,ApplnRoundingPrecision,NextTransactionNo,FirstNewVATEntryNo);
    
          IF NOT BlockPaymentTolerance THEN
            CalcPmtDiscTolerance(
              NewCVLedgEntryBuf,OldCVLedgEntryBuf,OldCVLedgEntryBuf2,DtldCVLedgEntryBuf,GenJnlLine,
              NextTransactionNo,FirstNewVATEntryNo);
    
          CalcCurrencyApplnRounding(
            NewCVLedgEntryBuf,OldCVLedgEntryBuf2,DtldCVLedgEntryBuf,
            GenJnlLine,ApplnRoundingPrecision);
    
          FindAmtForAppln(
            NewCVLedgEntryBuf,OldCVLedgEntryBuf,OldCVLedgEntryBuf2,
            AppliedAmount,AppliedAmountLCY,OldAppliedAmount,ApplnRoundingPrecision);
    
          CalcCurrencyUnrealizedGainLoss(
            OldCVLedgEntryBuf,DtldCVLedgEntryBuf,GenJnlLine,-OldAppliedAmount,OldRemainingAmtBeforeAppln);
    
          CalcCurrencyRealizedGainLoss(
            NewCVLedgEntryBuf,DtldCVLedgEntryBuf,GenJnlLine,AppliedAmount,AppliedAmountLCY);
    
          CalcCurrencyRealizedGainLoss(
            OldCVLedgEntryBuf,DtldCVLedgEntryBuf,GenJnlLine,-OldAppliedAmount,-AppliedAmountLCY);
    
          CalcApplication(
            NewCVLedgEntryBuf,OldCVLedgEntryBuf,DtldCVLedgEntryBuf,
            GenJnlLine,AppliedAmount,AppliedAmountLCY,OldAppliedAmount,
            NewCVLedgEntryBuf2,OldCVLedgEntryBuf3,AllApplied);
    
          PaymentToleranceMgt.CalcRemainingPmtDisc(NewCVLedgEntryBuf,OldCVLedgEntryBuf,OldCVLedgEntryBuf2,GLSetup);
    
          CalcAmtLCYAdjustment(OldCVLedgEntryBuf,DtldCVLedgEntryBuf,GenJnlLine);
        END;

    Also since NAV2013R2 RTM. So... In both cases it should be ApplyingDate or GenJnlLine."Posting Date", respectively. What makes me cautious is that it is this way since 4 years now... I would expect to have a calculation of all gains/losses against the applying date, which must be at least at the latest posting date of the entries in the application. Ideally, it should be explicitly specified (and used) if desired, even though it might mean that you have realized gains/losses that net each other out, partially or completely. So... I would suggest to open a support case for it?

    with best regards

    Jens

  • Suggested answer
    npanchal Profile Picture
    npanchal on at
    RE: Apply vendor ledger entries foreign currency not creating realized gain/loss

    I think following functional area you need to check.

    1. While you appling Payment, your exchange gain/ loss will be posed on payment date. so, at the date it seems ok to me

    2. while you apply invoice against the payment, your date of posting is as invoice date.

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

December Spotlight Star - Muhammad Affan

Congratulations to a top community star!

Top 10 leaders for November!

Congratulations to our November super stars!

Tips for Writing Effective Suggested Answers

Best practices for providing successful forum answers ✍️

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 291,269 Super User 2024 Season 2

#2
Martin Dráb Profile Picture

Martin Dráb 230,198 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,156

Leaderboard

Featured topics

Product updates

Dynamics 365 release plans