Международные предоплаты и российские авансы (часть 1)

Как известно в Dynamics NAV 5.0 была добавлена новая функциональность - Предоплаты.
Также известно, что в Dynamics NAV 4SP3 (и ранее) существовала локальная функциональность по учету Авансов (суть заключалась в учете полученных авансов на отдельном счете, а также обработке НДС, связанным с получением авансов).

Но, к сожалению, оба функционала вместе работать отказываются, тому есть ряд причин. Одна из них объективная – это действительно сложно.

В данной статье будут приведен перечень изменений, которые требуется выполнить, чтобы заставить работать оба функционала. Сразу отмечу, что они будут работать независимо друг от друга, т.е. для одного заказа можно будет использовать либо международные предоплаты, либо местные авансы.

Форма статьи – протокол изменений.

Отдельное спасибо DA_NEAL, который нашел и устранил баг, который в принципе не давал учесть документ после выставления счета на предоплату.

Таблица 379 Detailed Cust. Ledg. Entry
Переименовать поле 12401 Prepayment -> PrepaymentRU

Таблица 380 Detailed Vendor Ledg. Entry
Переименовать поле 12401 Prepayment -> PrepaymentRU

Таблица 383 Detailed CV Ledg. Entry Buffer
Переименовать поле 12401 Prepayment -> PrepaymentRU

Таблица 81 Gen. Journal Line
1. Добавить поле 50401 PrepaymentRU boolean

Перенести код из триггера поля Prepayment в PrepaymentRU

IF Prepayment THEN BEGIN      
 
  IF NOT ("Document Type" IN ["Document Type"::Payment,"Document Type"::Refund]) THEN      
 
    FIELDERROR("Document Type");      
 
  CLEAR("Applies-to Doc. Type");      
 
  CLEAR("Applies-to Doc. No.");      
 
END;

В будущем этот триггер придется изменить.

2. В триггере Document Type - OnValidate()
Код

IF NOT ("Document Type" IN ["Document Type"::Payment,"Document Type"::Refund]) THEN      
 
  Prepayment := FALSE;

Заменить кодом

IF NOT ("Document Type" IN ["Document Type"::Payment,"Document Type"::Refund]) THEN      
 
  PrepaymentRU := FALSE;

3. В триггере Applies-to Doc. Type - OnValidate()
Код

IF "Applies-to Doc. Type" <> "Applies-to Doc. Type"::" " THEN      
 
  TESTFIELD(Prepayment,FALSE);

Заменить кодом

IF "Applies-to Doc. Type" <> "Applies-to Doc. Type"::" " THEN      
 
  TESTFIELD(PrepaymentRU,FALSE);

4. В триггере Applies-to Doc. No. - OnValidate()
Код

IF "Applies-to Doc. No." <> '' THEN      
 
  TESTFIELD(Prepayment,FALSE);

Заменить кодом

IF "Applies-to Doc. No." <> '' THEN      
 
  TESTFIELD(PrepaymentRU,FALSE);

5. В триггере Applies-to Doc. No. - OnLookup()
Код

IF Prepayment THEN      
 
  EXIT;

Заменить кодом

IF PrepaymentRU THEN      
 
  EXIT;

Таблица 382 CV Ledger Entry Buffer
Добавить поле 50401 PrepaymentRU bollean

Таблица 21 Cust. Ledger Entry
Добавить поле 50401 PrepaymentRU bollean

Таблица 25 Vendor Ledger Entry
1. Добавить поле 50401 PrepaymentRU bollean

2. Код из триггера OnValidate поля Prepayment перенести в триггер onValidate поля PrepaymentRU и закомментировать. С ним мы разберемся позже.

Поля Prepayment международного функционала используются в таблицах 81,21, 382
Поля PrepaymentRU используются в таблицах 81, 21, 382, 383, 379
Переименовать поля локальной функциональности нужно, т.к. в одной таблице не может быть два поля с одинаковыми наименованиями.

Формы 12422 Bank Payment Order, 12423 Ingoing Cash Order CO-1, 12446 Vendor Entries Analysis
1. В функциях CalcPayment изменить строки

IF Prepayment THEN BEGIN

На

IF PrepaymentRU THEN BEGIN

(по две строки в каждой форме, всего шесть замен)

2. Изменить SourceExpr выключателя Аванс с Prepayment на PrepaymentRU

Формы 39 General Journal, 253 Sales Journal, 255 Cash Receipt Journal, 256 Payment Journal, 12424 Payment Order List
Изменить значение свойства SourceExpr в соотвествующем поле с Prepayment на PrepaymentRU

Отчеты 12402 Cash Outgoing Order CO-2, 12403 Cash Ingoing Order CO-1
В триггере onAfterGetRecord строки

IF Prepayment THEN

На

IF PrepaymentRU THEN

(по две строки в каждой форме, всего четыре замены)

Отчет 595 Adjust Exchange Rates
Все Prepayment, заменить на PrepaymentRU (замен много).

Программный модуль 11 Gen. Jnl.-Check Line
В функции RunCheck
Код

          IF ("Document Type" = "Document Type"::Payment) AND Prepayment THEN BEGIN      
 
            TESTFIELD("Applies-to Doc. Type",0);      
 
            TESTFIELD("Applies-to Doc. No.",'');      
 
          END;

Заменить кодом

          IF ("Document Type" = "Document Type"::Payment) AND PrepaymentRU THEN BEGIN      
 
            TESTFIELD("Applies-to Doc. Type",0);      
 
            TESTFIELD("Applies-to Doc. No.",'');      
 
          END;

Программный модуль 226 CustEntry-Apply Posted Entries
В триггере onRun
Код

GenJnlLine.Prepayment := Prepayment

Заменить кодом

GenJnlLine.PrepaymentRU := PrepaymentRU

Программный модуль 227 VendEntry-Apply Posted Entries
В триггере onRun
Код

GenJnlLine.Prepayment := Prepayment

Заменить кодом

GenJnlLine.PrepaymentRU := PrepaymentRU

Программные модули 442 Sales-Post Prepayments и 444 Purchase-Post Prepayments
Ничего не трогаем

Отчет 12453 Post Customer Prepayment
В триггере onAfterGetReccord
Код

IF SourceCustLedgEntry.Prepayment THEN BEGIN

Заменить кодом

IF SourceCustLedgEntry.PrepaymentRU THEN BEGIN

Программный модуль 12410 Customer Prepayment-Post
1. В триггере onRun
Код

TESTFIELD(Prepayment,PostingType = PostingType::Reset)

Заменить кодом

TESTFIELD(PrepaymentRU,PostingType = PostingType::Reset)

2. В функции PostPrepayment
Код

  GenJnlLine.Prepayment := TRUE

Заменить кодом

  GenJnlLine.PrepaymentRU := TRUE

Указанный код встречается дважды

Программный модуль 12 Gen. Jnl.-Post Line
1. Функция InsertVAT
Код

  VATEntry.Prepayment := Prepayment

Заменить кодом

  VATEntry.Prepayment := PrepaymentRU

2. Функция InsertVAT
Код

  IF GLSetup."Prepayment Unrealized VAT" AND NOT GLSetup."Unrealized VAT" AND      
 
    (VATPostingSetup."Unrealized VAT Type" > 0)      
 
  THEN      
 
    UnrealizedVAT := GenJnlLine.Prepayment;  UnrealizedVAT := UnrealizedVAT OR      
 
    (VATPostingSetup."Unrealized VAT Type" > 0) AND Prepayment AND      
 
    ("Document Type" = "Document Type"::Payment);

Заменить кодом

  IF GLSetup."Prepayment Unrealized VAT" AND NOT GLSetup."Unrealized VAT" AND      
 
    (VATPostingSetup."Unrealized VAT Type" > 0)      
 
  THEN      
 
    UnrealizedVAT := GenJnlLine.PrepaymentRU;  UnrealizedVAT := UnrealizedVAT OR      
 
    (VATPostingSetup."Unrealized VAT Type" > 0) AND PrepaymentRU AND      
 
    ("Document Type" = "Document Type"::Payment);

Очень подозрительный кусок. Требуется проверка.

3. Функция PostCust
Код

  CustLedgEntry."IC Partner Code" := "IC Partner Code";      
 
  CustLedgEntry.Prepayment := Prepayment;      
 
  CustLedgEntry."Prepayment Document No." := "Prepayment Document No.";

Заменить кодом

  CustLedgEntry."IC Partner Code" := "IC Partner Code";      
 
  CustLedgEntry.Prepayment := Prepayment;      
 
  CustLedgEntry.PrepaymentRU := PrepaymentRU;      
 
  CustLedgEntry."Prepayment Document No." := "Prepayment Document No.";

4. Функция PostVend
Код

  VendLedgEntry."IC Partner Code" := "IC Partner Code";      
 
  VendLedgEntry.Prepayment := Prepayment;      
 
  VendLedgEntry."Vendor VAT Invoice No." := "Vendor VAT Invoice No.";

Заменить кодом

  VendLedgEntry."IC Partner Code" := "IC Partner Code";      
 
  VendLedgEntry.Prepayment := Prepayment;      
 
  VendLedgEntry.PrepaymentRU := PrepaymentRU;      
 
  VendLedgEntry."Vendor VAT Invoice No." := "Vendor VAT Invoice No.";

5. Функция ApplyCustLedgEntry
Код

  IF NewCVLedgEntryBuf.Prepayment AND GenJnlLine.Correction THEN      
 
    ERROR(Text12450);      
 
  TempOldCustLedgEntry.SETRANGE(Positive,NewCVLedgEntryBuf."Remaining Amount" > 0);

Заменить кодом

  IF NewCVLedgEntryBuf.PrepaymentRU AND GenJnlLine.Correction THEN      
 
    ERROR(Text12450);      
 
  TempOldCustLedgEntry.SETRANGE(Positive,NewCVLedgEntryBuf."Remaining Amount" > 0);

6. Функция ApplyCustLedgEntry
Код

    IF (NewCVLedgEntryBuf."Currency Code" <> OldCustLedgEntry."Currency Code") THEN      
 
      IF (NewCVLedgEntryBuf."Amt. Diff. Appln. Entry No." = 0) AND (OldCustLedgEntry."Amt. Diff. Appln. Entry No." = 0) THEN      
 
        IF (NewCVLedgEntryBuf."Document Type" IN [2,3]) AND (OldCustLedgEntry."Document Type" IN [2,3]) OR      
 
         (NewCVLedgEntryBuf."Document Type" IN [1,6]) AND (OldCustLedgEntry."Document Type" IN [1,6])      
 
        THEN      
 
          ERROR(Text12412,NewCVLedgEntryBuf."Document Type",NewCVLedgEntryBuf."Currency Code",      
 
            OldCustLedgEntry."Document Type",OldCustLedgEntry."Currency Code");      
 
    AmtDiffDocToPrepayment := (NewCVLedgEntryBuf."Amt. Diff. Appln. Entry No." <> 0) AND OldCustLedgEntry.Prepayment;

Заменить кодом

    IF (NewCVLedgEntryBuf."Currency Code" <> OldCustLedgEntry."Currency Code") THEN      
 
      IF (NewCVLedgEntryBuf."Amt. Diff. Appln. Entry No." = 0) AND (OldCustLedgEntry."Amt. Diff. Appln. Entry No." = 0) THEN      
 
        IF (NewCVLedgEntryBuf."Document Type" IN [2,3]) AND (OldCustLedgEntry."Document Type" IN [2,3]) OR      
 
         (NewCVLedgEntryBuf."Document Type" IN [1,6]) AND (OldCustLedgEntry."Document Type" IN [1,6])      
 
        THEN      
 
          ERROR(Text12412,NewCVLedgEntryBuf."Document Type",NewCVLedgEntryBuf."Currency Code",      
 
            OldCustLedgEntry."Document Type",OldCustLedgEntry."Currency Code");      
 
    AmtDiffDocToPrepayment := (NewCVLedgEntryBuf."Amt. Diff. Appln. Entry No." <> 0) AND OldCustLedgEntry.PrepaymentRU;

7. Функция ApplyCustLedgEntry
Код

      IF (OldCustLedgEntry."Document Type" IN      
 
         [OldCustLedgEntry."Document Type"::" ",OldCustLedgEntry."Document Type"::Payment,      
 
          OldCustLedgEntry."Document Type"::Refund]) AND      
 
          NOT OldCustLedgEntry.Prepayment      
 
      THEN      
 
        ERROR(Text12411);

Заменить кодом

      IF (OldCustLedgEntry."Document Type" IN      
 
         [OldCustLedgEntry."Document Type"::" ",OldCustLedgEntry."Document Type"::Payment,      
 
          OldCustLedgEntry."Document Type"::Refund]) AND      
 
          NOT OldCustLedgEntry.PrepaymentRU      
 
      THEN      
 
        ERROR(Text12411);

8. Функция ApplyCustLedgEntry
Код

  IF NOT AmtDiffDocToPrepayment THEN      
 
  IF GLSetup."Unrealized VAT" OR      
 
    (GLSetup."Prepayment Unrealized VAT" AND TempOldCustLedgEntry.Prepayment)      
 
  THEN BEGIN // TODO

Заменить кодом

  IF NOT AmtDiffDocToPrepayment THEN      
 
  IF GLSetup."Unrealized VAT" OR      
 
    (GLSetup."Prepayment Unrealized VAT" AND TempOldCustLedgEntry.PrepaymentRU)      
 
  THEN BEGIN // TODO

Хотя с этим фрагментом нужно будет разбираться отдельно. Уж очень он подозрителен.

9. Функция ApplyCustLedgEntry
Код

IF NOT AmtDiffDocToPrepayment THEN      
 
IF GLSetup."Unrealized VAT" OR      
 
  (GLSetup."Prepayment Unrealized VAT" AND NewCustLedgEntry.Prepayment)      
 
THEN BEGIN // TODO

Заменить кодом

IF NOT AmtDiffDocToPrepayment THEN      
 
IF GLSetup."Unrealized VAT" OR      
 
  (GLSetup."Prepayment Unrealized VAT" AND NewCustLedgEntry.PrepaymentRU)      
 
THEN BEGIN // TODO

И с этим тоже нужно будет разбираться отдельно.

10. Фунция CalcAmtLCYAdjustment
Код

IF GLSetup."Cancel Curr. Prepmt. Adjmt." AND CVLedgEntryBuf.Prepayment THEN      
 
  EXIT;

Заменить кодом

IF GLSetup."Cancel Curr. Prepmt. Adjmt." AND CVLedgEntryBuf.PrepaymentRU THEN      
 
  EXIT;

11. Функция InsertDtldCVLedgEntry
Код

NewDtldCVLedgEntryBuf := DtldCVLedgEntryBuf;      
 
NewDtldCVLedgEntryBuf.PrepaymentRU := CVLedgEntryBuf.Prepayment;      
 
NewDtldCVLedgEntryBuf."Amount Difference" :=

Заменить кодом

NewDtldCVLedgEntryBuf := DtldCVLedgEntryBuf;      
 
NewDtldCVLedgEntryBuf.PrepaymentRU := CVLedgEntryBuf.PrepaymentRU;      
 
NewDtldCVLedgEntryBuf."Amount Difference" :=

В строке NewDtldCVLedgEntryBuf.PrepaymentRU уже отображается PrepaymentRU, т.к. ранее мы выполнили переименование поля в таблице.

12. Из функции TransferCustLedgEntr удалить строки

  CVLedgEntryBuf.Prepayment := CustLedgEntry.Prepayment;

И

  CustLedgEntry.Prepayment := CVLedgEntryBuf.Prepayment;

Оба значения хорошо перенесутся функцией Transfield т.к. у Prepayment в обеих таблицах ID 90, а у PrepaymentRU - 50401.

13. В функции ApplyVendLedgEntry
Код

  IF GLSetup."Unrealized VAT" OR      
 
    (GLSetup."Prepayment Unrealized VAT" AND OldVendLedgEntry.Prepayment)      
 
  THEN BEGIN // TODO

Заменить кодом

  IF GLSetup."Unrealized VAT" OR      
 
    (GLSetup."Prepayment Unrealized VAT" AND OldVendLedgEntry.PrepaymentRU)      
 
  THEN BEGIN // TODO

Хотя с этим фрагментом нужно будет разбираться отдельно. Уж очень он подозрителен.

14. В функции ApplyVendLedgEntry
Код

IF GLSetup."Unrealized VAT" OR      
 
  (GLSetup."Prepayment Unrealized VAT" AND NewVendLedgEntry.Prepayment)      
 
THEN BEGIN // TODO

Заменить кодом

IF GLSetup."Unrealized VAT" OR      
 
  (GLSetup."Prepayment Unrealized VAT" AND NewVendLedgEntry.PrepaymentRU)      
 
THEN BEGIN // TODO

Хотя с этим фрагментом нужно будет разбираться отдельно. Уж очень он подозрителен.

15. В функции TransferVendLedgEntr
Код

  CVLedgEntryBuf.Prepayment := VendLedgEntry.Prepayment

Заменить кодом

  CVLedgEntryBuf.Prepayment := VendLedgEntry.Prepayment      
 
  CVLedgEntryBuf.PrepaymentRU := VendLedgEntry.PrepaymentRU

16. В функции TransferVendLedgEntr
Код

  VendLedgEntry.Prepayment := CVLedgEntryBuf.Prepayment

Заменить кодом

  VendLedgEntry.Prepayment := CVLedgEntryBuf.Prepayment      
 
  VendLedgEntry.PrepaymentRU := CVLedgEntryBuf.PrepaymentRU

17. В функции PostCustPrepayment
Код

    TempGenJnlLine."Document No." := "Document No.";      
 
    TempGenJnlLine.Prepayment := Prepayment;      
 
    TempGenJnlLine.VALIDATE("Account No.",GLEntry."G/L Account No.");

Заменить кодом

    TempGenJnlLine."Document No." := "Document No.";      
 
    TempGenJnlLine.Prepayment := Prepayment;      
 
    TempGenJnlLine.PrepaymentRU := PrepaymentRU;      
 
    TempGenJnlLine.VALIDATE("Account No.",GLEntry."G/L Account No.");

18. В функции RUFindAmtForAppln
Код

  IF GLSetup."Cancel Curr. Prepmt. Adjmt." AND PayEntryBuf.Prepayment THEN      
 
    AppliedAmountLCY := ROUND(OldAppliedAmount / PayEntryBuf."Original Currency Factor");

Заменить кодом

  IF GLSetup."Cancel Curr. Prepmt. Adjmt." AND PayEntryBuf.PrepaymentRU THEN      
 
    AppliedAmountLCY := ROUND(OldAppliedAmount / PayEntryBuf."Original Currency Factor");

19. В функции CalcTaxAccRealizedGainLossAmt
Код

IF NOT CVLedgEntryBuf.Prepayment THEN      
 
  EXIT;

Заменить кодом

IF NOT CVLedgEntryBuf.PrepaymentRU THEN      
 
  EXIT;

Форма 302 Customer Entry Statistics

Prepayment заменить на PrepaymentRU (4 вхождения)

Форма 302 Vendor Entry Statistics

Prepayment заменить на PrepaymentRU (4 вхождения)

Форма 402 Sales Order Statistics

Код

END      
 
TempSalesLine.DELETEALL

Заменить кодом

END;      
 
TempSalesLine.RESET;      
 
TempSalesLine.DELETEALL;

Программный модуль 80 Sales-Post
1. В функцию IncrAmount
Код

  Increment(TotalSalesLine."Inv. Disc. Amount to Invoice","Inv. Disc. Amount to Invoice");      
 
END;

Заменить кодом

  Increment(TotalSalesLine."Inv. Disc. Amount to Invoice","Inv. Disc. Amount to Invoice");      
 
  Increment(TotalSalesLine."Prepmt. Amt. Inv.","Prepmt. Amt. Inv.");      
 
  Increment(TotalSalesLine."Prepmt Amt to Deduct","Prepmt Amt to Deduct");      
 
  Increment(TotalSalesLine."Prepmt Amt Deducted","Prepmt Amt Deducted");      
 
END;

2.В триггере onRun
Код

  TempVATAmountLineRemainder.DELETEALL;      
 
  SalesLine.CalcVATAmountLines(1,SalesHeader,SalesLine,TempVATAmountLine);

Заменить

  TempVATAmountLineRemainder.DELETEALL;      
 
  SalesLine.CalcVATAmountLines(1,SalesHeader,CombinedSalesLineTemp,TempVATAmountLine);

Стоит отдельно отметить, что некоторые изменения требуют дополнительного тестирования и осмысливания, что планируется выполнить при написании продолжения. Кроме того есть желание написать методологические рекомендации по работе с международным функционалом предоплат.

Замечания и советы, можно оставлять в комментариях, а если новая защита от спам-ботов окажется непроходимой – то пишите прямо мне на почту apanko@nav4u.ru.

PS. Со времени написания статьи до ее опубликования поставщик выпустил обновления касающиеся НДС с авансов. Следует это учитывать при использовании информации из данной статьи.

Метки:



Оставьте свой отзыв!