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