Международные предоплаты и российские авансы (часть 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. Со времени написания статьи до ее опубликования поставщик выпустил обновления касающиеся НДС с авансов. Следует это учитывать при использовании информации из данной статьи.
Метки: Андрей Панько