Codeunit 7000 Sales Price Calc. Mgt.
- App
- Base Application
- Namespace
- Microsoft.Sales.Pricing
- Versions
- 17-28
Procedures, 70Events, 104Obsolete, 23
Versions171819202122232425262728
Source29
Source in 29
src/Layers/W1/BaseApp/Sales/Pricing/SalesPriceCalcMgt.Codeunit.al2372 lines, Copyright (c) Microsoft Corporation. MIT
// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------
namespace Microsoft.Sales.Pricing;
using Microsoft.CRM.Campaign;
using Microsoft.CRM.Contact;
using Microsoft.Finance.Currency;
using Microsoft.Finance.GeneralLedger.Setup;
using Microsoft.Finance.VAT.Setup;
using Microsoft.Inventory.Item;
using Microsoft.Inventory.Journal;
using Microsoft.Projects.Project.Job;
using Microsoft.Projects.Project.Journal;
using Microsoft.Projects.Project.Planning;
using Microsoft.Projects.Project.Pricing;
using Microsoft.Projects.Resources.Journal;
using Microsoft.Projects.Resources.Pricing;
using Microsoft.Projects.Resources.Resource;
using Microsoft.Sales.Document;
/// <summary>
/// Provides sales price calculation logic including best price determination, discount calculation, and VAT handling.
/// </summary>
codeunit 7000 "Sales Price Calc. Mgt."
{
trigger OnRun()
begin
end;
var
GLSetup: Record "General Ledger Setup";
Item: Record Item;
ResPrice: Record "Resource Price";
Res: Record Resource;
Currency: Record Currency;
TempSalesPrice: Record "Sales Price" temporary;
TempSalesLineDisc: Record "Sales Line Discount" temporary;
#if not CLEAN28
ServPriceCalcMgt: Codeunit "Serv. Price Calc. Mgt.";
#endif
LineDiscPerCent: Decimal;
Qty: Decimal;
AllowLineDisc: Boolean;
AllowInvDisc: Boolean;
VATPerCent: Decimal;
PricesInclVAT: Boolean;
VATCalcType: Option "Normal VAT","Reverse Charge VAT","Full VAT","Sales Tax";
VATBusPostingGr: Code[20];
QtyPerUOM: Decimal;
PricesInCurrency: Boolean;
CurrencyFactor: Decimal;
ExchRateDate: Date;
FoundSalesPrice: Boolean;
DateCaption: Text[30];
#pragma warning disable AA0074
#pragma warning disable AA0470
Text000: Label '%1 is less than %2 in the %3.';
Text010: Label 'Prices including VAT cannot be calculated when %1 is %2.';
Text001: Label 'The %1 in the %2 must be same as in the %3.';
#pragma warning restore AA0470
#pragma warning restore AA0074
TempTableErr: Label 'The table passed as a parameter must be temporary.';
/// <summary>
/// Finds and applies the best price for a sales line based on customer, item, and pricing agreements.
/// </summary>
/// <param name="SalesHeader">Specifies the sales header containing customer and currency information.</param>
/// <param name="SalesLine">Specifies the sales line to calculate the price for.</param>
/// <param name="CalledByFieldNo">Specifies the field number that triggered the price calculation.</param>
procedure FindSalesLinePrice(SalesHeader: Record "Sales Header"; var SalesLine: Record "Sales Line"; CalledByFieldNo: Integer)
var
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeFindSalesLinePrice(SalesLine, SalesHeader, CalledByFieldNo, IsHandled);
if IsHandled then
exit;
SetCurrency(SalesHeader."Currency Code", SalesHeader."Currency Factor", SalesHeaderExchDate(SalesHeader));
SetVAT(SalesHeader."Prices Including VAT", SalesLine.GetVATPct(), SalesLine."VAT Calculation Type".AsInteger(), SalesLine."VAT Bus. Posting Group");
SetUoM(Abs(SalesLine.Quantity), SalesLine."Qty. per Unit of Measure");
SetLineDisc(SalesLine."Line Discount %", SalesLine."Allow Line Disc.", SalesLine."Allow Invoice Disc.");
OnFindSalesLinePriceOnAfterSetLineDisc(SalesLine, Qty, QtyPerUOM);
SalesLine.TestField("Qty. per Unit of Measure");
if PricesInCurrency then
SalesHeader.TestField("Currency Factor");
case SalesLine.Type of
SalesLine.Type::Item:
begin
Item.Get(SalesLine."No.");
SalesLinePriceExists(SalesHeader, SalesLine, false);
OnFindSalesLinePriceOnCalcBestUnitPrice(SalesLine, TempSalesPrice);
CalcBestUnitPrice(TempSalesPrice);
OnAfterFindSalesLineItemPrice(SalesLine, TempSalesPrice, FoundSalesPrice, CalledByFieldNo);
if FoundSalesPrice or
not ((CalledByFieldNo = SalesLine.FieldNo(Quantity)) or
(CalledByFieldNo = SalesLine.FieldNo("Variant Code")))
then begin
SalesLine."Allow Line Disc." := TempSalesPrice."Allow Line Disc.";
SalesLine."Allow Invoice Disc." := TempSalesPrice."Allow Invoice Disc.";
SalesLine."Unit Price" := TempSalesPrice."Unit Price";
OnFindSalesLinePriceOnItemTypeOnAfterSetUnitPrice(SalesHeader, SalesLine, TempSalesPrice, CalledByFieldNo, FoundSalesPrice);
end;
if not SalesLine."Allow Line Disc." then
SalesLine."Line Discount %" := 0;
end;
SalesLine.Type::Resource:
begin
SetResPrice(SalesLine."No.", SalesLine."Work Type Code", SalesLine."Currency Code");
OnFindSalesLinePriceOnAfterSetResPrice(SalesLine, ResPrice);
CODEUNIT.Run(CODEUNIT::"Resource-Find Price", ResPrice);
OnAfterFindSalesLineResPrice(SalesLine, ResPrice, CalledByFieldNo);
if not (CalledByFieldNo = SalesLine.FieldNo(Quantity)) then begin
ConvertPriceToVAT(false, '', '', ResPrice."Unit Price");
ConvertPriceLCYToFCY(ResPrice."Currency Code", ResPrice."Unit Price");
SalesLine."Unit Price" := ResPrice."Unit Price" * SalesLine."Qty. per Unit of Measure";
end;
end;
end;
OnAfterFindSalesLinePrice(
SalesLine, SalesHeader, TempSalesPrice, ResPrice, CalledByFieldNo, FoundSalesPrice,
Qty, QtyPerUOM, LineDiscPerCent, AllowLineDisc, AllowInvDisc, PricesInCurrency,
VATBusPostingGr, VATCalcType, VATPerCent, CurrencyFactor);
end;
/// <summary>
/// Finds and applies the best sales price for an item journal line.
/// </summary>
/// <param name="ItemJnlLine">Specifies the item journal line to calculate the price for.</param>
/// <param name="CalledByFieldNo">Specifies the field number that triggered the price calculation.</param>
procedure FindItemJnlLinePrice(var ItemJnlLine: Record "Item Journal Line"; CalledByFieldNo: Integer)
var
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeFindItemJnlLinePrice(ItemJnlLine, CalledByFieldNo, IsHandled);
if IsHandled then
exit;
SetCurrency('', 0, 0D);
SetVAT(false, 0, 0, '');
SetUoM(Abs(ItemJnlLine.Quantity), ItemJnlLine."Qty. per Unit of Measure");
ItemJnlLine.TestField("Qty. per Unit of Measure");
Item.Get(ItemJnlLine."Item No.");
FindSalesPrice(
TempSalesPrice, '', '', '', '', ItemJnlLine."Item No.", ItemJnlLine."Variant Code",
ItemJnlLine."Unit of Measure Code", '', ItemJnlLine."Posting Date", false);
CalcBestUnitPrice(TempSalesPrice);
if FoundSalesPrice or
not ((CalledByFieldNo = ItemJnlLine.FieldNo(Quantity)) or
(CalledByFieldNo = ItemJnlLine.FieldNo("Variant Code")))
then
ItemJnlLine.Validate("Unit Amount", TempSalesPrice."Unit Price");
OnAfterFindItemJnlLinePrice(ItemJnlLine, TempSalesPrice, CalledByFieldNo, FoundSalesPrice);
end;
#if not CLEAN28
/// <summary>
/// Finds and applies the best sales price for a service line.
/// </summary>
/// <param name="ServHeader">The service header containing customer information.</param>
/// <param name="ServLine">The service line to calculate the price for.</param>
/// <param name="CalledByFieldNo">The field number that triggered the price calculation.</param>
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
procedure FindServLinePrice(ServHeader: Record Microsoft.Service.Document."Service Header"; var ServLine: Record Microsoft.Service.Document."Service Line"; CalledByFieldNo: Integer)
begin
ServPriceCalcMgt.FindServLinePrice(ServHeader, ServLine, CalledByFieldNo);
end;
#endif
/// <summary>
/// Finds and applies the best line discount for a sales line based on customer and item discount groups.
/// </summary>
/// <param name="SalesHeader">Specifies the sales header containing customer information.</param>
/// <param name="SalesLine">Specifies the sales line to calculate the discount for.</param>
procedure FindSalesLineLineDisc(SalesHeader: Record "Sales Header"; var SalesLine: Record "Sales Line")
var
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeFindSalesLineLineDisc(SalesLine, SalesHeader, IsHandled);
if IsHandled then
exit;
SetCurrency(SalesHeader."Currency Code", 0, 0D);
SetUoM(Abs(SalesLine.Quantity), SalesLine."Qty. per Unit of Measure");
SalesLine.TestField("Qty. per Unit of Measure");
IsHandled := false;
OnFindSalesLineLineDiscOnBeforeCalcLineDisc(SalesHeader, SalesLine, TempSalesLineDisc, Qty, QtyPerUOM, IsHandled);
if not IsHandled then
if SalesLine.Type = SalesLine.Type::Item then begin
SalesLineLineDiscExists(SalesHeader, SalesLine, false);
CalcBestLineDisc(TempSalesLineDisc);
SalesLine."Line Discount %" := TempSalesLineDisc."Line Discount %";
end;
OnAfterFindSalesLineLineDisc(SalesLine, SalesHeader, TempSalesLineDisc);
end;
#if not CLEAN28
/// <summary>
/// Finds and applies the best line discount for a service line.
/// </summary>
/// <param name="ServHeader">The service header containing customer information.</param>
/// <param name="ServLine">The service line to calculate the discount for.</param>
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
procedure FindServLineDisc(ServHeader: Record Microsoft.Service.Document."Service Header"; var ServLine: Record Microsoft.Service.Document."Service Line")
begin
ServPriceCalcMgt.FindServLineDisc(ServHeader, ServLine);
end;
#endif
/// <summary>
/// Finds and applies the best sales price for a standard item journal line.
/// </summary>
/// <param name="StdItemJnlLine">Specifies the standard item journal line to calculate the price for.</param>
/// <param name="CalledByFieldNo">Specifies the field number that triggered the price calculation.</param>
procedure FindStdItemJnlLinePrice(var StdItemJnlLine: Record "Standard Item Journal Line"; CalledByFieldNo: Integer)
var
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeFindStdItemJnlLinePrice(StdItemJnlLine, CalledByFieldNo, IsHandled);
if IsHandled then
exit;
SetCurrency('', 0, 0D);
SetVAT(false, 0, 0, '');
SetUoM(Abs(StdItemJnlLine.Quantity), StdItemJnlLine."Qty. per Unit of Measure");
StdItemJnlLine.TestField("Qty. per Unit of Measure");
Item.Get(StdItemJnlLine."Item No.");
FindSalesPrice(
TempSalesPrice, '', '', '', '', StdItemJnlLine."Item No.", StdItemJnlLine."Variant Code",
StdItemJnlLine."Unit of Measure Code", '', WorkDate(), false);
CalcBestUnitPrice(TempSalesPrice);
if FoundSalesPrice or
not ((CalledByFieldNo = StdItemJnlLine.FieldNo(Quantity)) or
(CalledByFieldNo = StdItemJnlLine.FieldNo("Variant Code")))
then
StdItemJnlLine.Validate("Unit Amount", TempSalesPrice."Unit Price");
OnAfterFindStdItemJnlLinePrice(StdItemJnlLine, TempSalesPrice, CalledByFieldNo);
end;
/// <summary>
/// Finds the best sales price for an item to be used in analysis reports.
/// </summary>
/// <param name="ItemNo">Specifies the item number to find the price for.</param>
/// <param name="Date">Specifies the date for the price lookup.</param>
/// <returns>The unit price for the item, or the item's default unit price if no sales price is found.</returns>
procedure FindAnalysisReportPrice(ItemNo: Code[20]; Date: Date): Decimal
var
UnitPrice: Decimal;
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeFindAnalysisReportPrice(ItemNo, Date, UnitPrice, IsHandled, FoundSalesPrice);
if IsHandled then
exit(UnitPrice);
SetCurrency('', 0, 0D);
SetVAT(false, 0, 0, '');
SetUoM(0, 1);
Item.Get(ItemNo);
FindSalesPrice(TempSalesPrice, '', '', '', '', ItemNo, '', '', '', Date, false);
CalcBestUnitPrice(TempSalesPrice);
if FoundSalesPrice then
exit(TempSalesPrice."Unit Price");
exit(Item."Unit Price");
end;
/// <summary>
/// Calculates the best unit price from a set of sales prices, considering currency, variant, and minimum quantity requirements.
/// </summary>
/// <param name="SalesPrice">Specifies the sales price record set to evaluate. Returns the best price found.</param>
procedure CalcBestUnitPrice(var SalesPrice: Record "Sales Price")
var
BestSalesPrice: Record "Sales Price";
BestSalesPriceFound: Boolean;
IsHandled: Boolean;
begin
OnBeforeCalcBestUnitPrice(SalesPrice, IsHandled);
if IsHandled then
exit;
FoundSalesPrice := SalesPrice.FindSet();
if FoundSalesPrice then
repeat
IsHandled := false;
OnCalcBestUnitPriceOnBeforeCalcBestUnitPriceConvertPrice(
SalesPrice, Qty, IsHandled, Item, QtyPerUOM, BestSalesPrice, BestSalesPriceFound,
VATCalcType, PricesInclVAT, VATPerCent, PricesInCurrency, ExchRateDate, CurrencyFactor,
Currency, LineDiscPerCent, VATBusPostingGr);
if not IsHandled then
if IsInMinQty(SalesPrice."Unit of Measure Code", SalesPrice."Minimum Quantity") then begin
CalcBestUnitPriceConvertPrice(SalesPrice);
case true of
((BestSalesPrice."Currency Code" = '') and (SalesPrice."Currency Code" <> '')) or
((BestSalesPrice."Variant Code" = '') and (SalesPrice."Variant Code" <> '')):
begin
BestSalesPrice := SalesPrice;
BestSalesPriceFound := true;
end;
((BestSalesPrice."Currency Code" = '') or (SalesPrice."Currency Code" <> '')) and
((BestSalesPrice."Variant Code" = '') or (SalesPrice."Variant Code" <> '')):
if (BestSalesPrice."Unit Price" = 0) or
(CalcLineAmount(BestSalesPrice) > CalcLineAmount(SalesPrice))
then begin
BestSalesPrice := SalesPrice;
BestSalesPriceFound := true;
end;
end;
end;
until SalesPrice.Next() = 0;
OnAfterCalcBestUnitPrice(SalesPrice, BestSalesPrice, FoundSalesPrice);
// No price found in agreement
if not BestSalesPriceFound then begin
ConvertPriceToVAT(
Item."Price Includes VAT", Item."VAT Prod. Posting Group",
Item."VAT Bus. Posting Gr. (Price)", Item."Unit Price");
ConvertPriceToUoM('', Item."Unit Price");
ConvertPriceLCYToFCY('', Item."Unit Price");
Clear(BestSalesPrice);
BestSalesPrice."Unit Price" := Item."Unit Price";
BestSalesPrice."Allow Line Disc." := AllowLineDisc;
BestSalesPrice."Allow Invoice Disc." := AllowInvDisc;
OnAfterCalcBestUnitPriceAsItemUnitPrice(BestSalesPrice, Item);
end;
SalesPrice := BestSalesPrice;
end;
local procedure CalcBestUnitPriceConvertPrice(var SalesPrice: Record "Sales Price")
var
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeCalcBestUnitPriceConvertPrice(SalesPrice, IsHandled, Item);
if IsHandled then
exit;
ConvertPriceToVAT(
SalesPrice."Price Includes VAT", Item."VAT Prod. Posting Group",
SalesPrice."VAT Bus. Posting Gr. (Price)", SalesPrice."Unit Price");
ConvertPriceToUoM(SalesPrice."Unit of Measure Code", SalesPrice."Unit Price");
ConvertPriceLCYToFCY(SalesPrice."Currency Code", SalesPrice."Unit Price");
end;
/// <summary>
/// Calculates the best line discount from a set of sales line discounts, considering currency, variant, and minimum quantity requirements.
/// </summary>
/// <param name="SalesLineDisc">Specifies the sales line discount record set to evaluate. Returns the best discount found.</param>
procedure CalcBestLineDisc(var SalesLineDisc: Record "Sales Line Discount")
var
BestSalesLineDisc: Record "Sales Line Discount";
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeCalcBestLineDisc(SalesLineDisc, Item, IsHandled, QtyPerUOM, Qty);
if IsHandled then
exit;
if SalesLineDisc.FindSet() then
repeat
if IsInMinQty(SalesLineDisc."Unit of Measure Code", SalesLineDisc."Minimum Quantity") then
case true of
((BestSalesLineDisc."Currency Code" = '') and (SalesLineDisc."Currency Code" <> '')) or
((BestSalesLineDisc."Variant Code" = '') and (SalesLineDisc."Variant Code" <> '')):
BestSalesLineDisc := SalesLineDisc;
((BestSalesLineDisc."Currency Code" = '') or (SalesLineDisc."Currency Code" <> '')) and
((BestSalesLineDisc."Variant Code" = '') or (SalesLineDisc."Variant Code" <> '')):
if BestSalesLineDisc."Line Discount %" < SalesLineDisc."Line Discount %" then
BestSalesLineDisc := SalesLineDisc;
end;
until SalesLineDisc.Next() = 0;
SalesLineDisc := BestSalesLineDisc;
end;
/// <summary>
/// Finds all applicable sales prices for an item based on customer, contact, price group, and campaign criteria.
/// </summary>
/// <param name="ToSalesPrice">Returns the temporary sales price records found.</param>
/// <param name="CustNo">Specifies the customer number to search prices for.</param>
/// <param name="ContNo">Specifies the contact number to search prices for.</param>
/// <param name="CustPriceGrCode">Specifies the customer price group code to search prices for.</param>
/// <param name="CampaignNo">Specifies the campaign number to search prices for.</param>
/// <param name="ItemNo">Specifies the item number to find prices for.</param>
/// <param name="VariantCode">Specifies the item variant code to filter prices by.</param>
/// <param name="UOM">Specifies the unit of measure code to filter prices by.</param>
/// <param name="CurrencyCode">Specifies the currency code to filter prices by.</param>
/// <param name="StartingDate">Specifies the date to filter valid prices by.</param>
/// <param name="ShowAll">Specifies whether to show all prices or only applicable ones.</param>
procedure FindSalesPrice(var ToSalesPrice: Record "Sales Price"; CustNo: Code[20]; ContNo: Code[20]; CustPriceGrCode: Code[10]; CampaignNo: Code[20]; ItemNo: Code[20]; VariantCode: Code[10]; UOM: Code[10]; CurrencyCode: Code[10]; StartingDate: Date; ShowAll: Boolean)
var
FromSalesPrice: Record "Sales Price";
TempTargetCampaignGr: Record "Campaign Target Group" temporary;
begin
if not ToSalesPrice.IsTemporary then
Error(TempTableErr);
ToSalesPrice.Reset();
ToSalesPrice.DeleteAll();
OnBeforeFindSalesPrice(
ToSalesPrice, FromSalesPrice, QtyPerUOM, Qty, CustNo, ContNo, CustPriceGrCode, CampaignNo,
ItemNo, VariantCode, UOM, CurrencyCode, StartingDate, ShowAll);
FromSalesPrice.SetRange("Item No.", ItemNo);
FromSalesPrice.SetFilter("Variant Code", '%1|%2', VariantCode, '');
FromSalesPrice.SetFilter("Ending Date", '%1|>=%2', 0D, StartingDate);
if not ShowAll then begin
FromSalesPrice.SetFilter("Currency Code", '%1|%2', CurrencyCode, '');
if UOM <> '' then
FromSalesPrice.SetFilter("Unit of Measure Code", '%1|%2', UOM, '');
FromSalesPrice.SetRange("Starting Date", 0D, StartingDate);
end;
FromSalesPrice.SetRange("Sales Type", FromSalesPrice."Sales Type"::"All Customers");
FromSalesPrice.SetRange("Sales Code");
CopySalesPriceToSalesPrice(FromSalesPrice, ToSalesPrice);
if CustNo <> '' then begin
FromSalesPrice.SetRange("Sales Type", FromSalesPrice."Sales Type"::Customer);
FromSalesPrice.SetRange("Sales Code", CustNo);
CopySalesPriceToSalesPrice(FromSalesPrice, ToSalesPrice);
end;
if CustPriceGrCode <> '' then begin
FromSalesPrice.SetRange("Sales Type", FromSalesPrice."Sales Type"::"Customer Price Group");
FromSalesPrice.SetRange("Sales Code", CustPriceGrCode);
CopySalesPriceToSalesPrice(FromSalesPrice, ToSalesPrice);
end;
if not ((CustNo = '') and (ContNo = '') and (CampaignNo = '')) then begin
FromSalesPrice.SetRange("Sales Type", FromSalesPrice."Sales Type"::Campaign);
if ActivatedCampaignExists(TempTargetCampaignGr, CustNo, ContNo, CampaignNo) then
repeat
FromSalesPrice.SetRange("Sales Code", TempTargetCampaignGr."Campaign No.");
CopySalesPriceToSalesPrice(FromSalesPrice, ToSalesPrice);
until TempTargetCampaignGr.Next() = 0;
end;
OnAfterFindSalesPrice(
ToSalesPrice, FromSalesPrice, QtyPerUOM, Qty, CustNo, ContNo, CustPriceGrCode, CampaignNo,
ItemNo, VariantCode, UOM, CurrencyCode, StartingDate, ShowAll);
end;
/// <summary>
/// Finds all applicable sales line discounts for an item based on customer, contact, discount group, and campaign criteria.
/// </summary>
/// <param name="ToSalesLineDisc">Returns the temporary sales line discount records found.</param>
/// <param name="CustNo">Specifies the customer number to search discounts for.</param>
/// <param name="ContNo">Specifies the contact number to search discounts for.</param>
/// <param name="CustDiscGrCode">Specifies the customer discount group code to search discounts for.</param>
/// <param name="CampaignNo">Specifies the campaign number to search discounts for.</param>
/// <param name="ItemNo">Specifies the item number to find discounts for.</param>
/// <param name="ItemDiscGrCode">Specifies the item discount group code to search discounts for.</param>
/// <param name="VariantCode">Specifies the item variant code to filter discounts by.</param>
/// <param name="UOM">Specifies the unit of measure code to filter discounts by.</param>
/// <param name="CurrencyCode">Specifies the currency code to filter discounts by.</param>
/// <param name="StartingDate">Specifies the date to filter valid discounts by.</param>
/// <param name="ShowAll">Specifies whether to show all discounts or only applicable ones.</param>
procedure FindSalesLineDisc(var ToSalesLineDisc: Record "Sales Line Discount"; CustNo: Code[20]; ContNo: Code[20]; CustDiscGrCode: Code[20]; CampaignNo: Code[20]; ItemNo: Code[20]; ItemDiscGrCode: Code[20]; VariantCode: Code[10]; UOM: Code[10]; CurrencyCode: Code[10]; StartingDate: Date; ShowAll: Boolean)
var
FromSalesLineDisc: Record "Sales Line Discount";
TempCampaignTargetGr: Record "Campaign Target Group" temporary;
InclCampaigns: Boolean;
begin
OnBeforeFindSalesLineDisc(
ToSalesLineDisc, CustNo, ContNo, CustDiscGrCode, CampaignNo, ItemNo, ItemDiscGrCode, VariantCode, UOM,
CurrencyCode, StartingDate, ShowAll);
FromSalesLineDisc.SetFilter("Ending Date", '%1|>=%2', 0D, StartingDate);
FromSalesLineDisc.SetFilter("Variant Code", '%1|%2', VariantCode, '');
OnFindSalesLineDiscOnAfterSetFilters(FromSalesLineDisc);
if not ShowAll then begin
FromSalesLineDisc.SetRange("Starting Date", 0D, StartingDate);
FromSalesLineDisc.SetFilter("Currency Code", '%1|%2', CurrencyCode, '');
if UOM <> '' then
FromSalesLineDisc.SetFilter("Unit of Measure Code", '%1|%2', UOM, '');
end;
ToSalesLineDisc.Reset();
ToSalesLineDisc.DeleteAll();
for FromSalesLineDisc."Sales Type" := FromSalesLineDisc."Sales Type"::Customer to FromSalesLineDisc."Sales Type"::Campaign do
if (FromSalesLineDisc."Sales Type" = FromSalesLineDisc."Sales Type"::"All Customers") or
((FromSalesLineDisc."Sales Type" = FromSalesLineDisc."Sales Type"::Customer) and (CustNo <> '')) or
((FromSalesLineDisc."Sales Type" = FromSalesLineDisc."Sales Type"::"Customer Disc. Group") and (CustDiscGrCode <> '')) or
((FromSalesLineDisc."Sales Type" = FromSalesLineDisc."Sales Type"::Campaign) and
not ((CustNo = '') and (ContNo = '') and (CampaignNo = '')))
then begin
InclCampaigns := false;
FromSalesLineDisc.SetRange("Sales Type", FromSalesLineDisc."Sales Type");
case FromSalesLineDisc."Sales Type" of
FromSalesLineDisc."Sales Type"::"All Customers":
FromSalesLineDisc.SetRange("Sales Code");
FromSalesLineDisc."Sales Type"::Customer:
FromSalesLineDisc.SetRange("Sales Code", CustNo);
FromSalesLineDisc."Sales Type"::"Customer Disc. Group":
FromSalesLineDisc.SetRange("Sales Code", CustDiscGrCode);
FromSalesLineDisc."Sales Type"::Campaign:
begin
InclCampaigns := ActivatedCampaignExists(TempCampaignTargetGr, CustNo, ContNo, CampaignNo);
FromSalesLineDisc.SetRange("Sales Code", TempCampaignTargetGr."Campaign No.");
end;
end;
repeat
FromSalesLineDisc.SetRange(Type, FromSalesLineDisc.Type::Item);
FromSalesLineDisc.SetRange(Code, ItemNo);
CopySalesDiscToSalesDisc(FromSalesLineDisc, ToSalesLineDisc);
if ItemDiscGrCode <> '' then begin
FromSalesLineDisc.SetRange(Type, FromSalesLineDisc.Type::"Item Disc. Group");
FromSalesLineDisc.SetRange(Code, ItemDiscGrCode);
CopySalesDiscToSalesDisc(FromSalesLineDisc, ToSalesLineDisc);
end;
OnFindSalesLineDiscOnAfterCopyItemDiscGroup(FromSalesLineDisc, ToSalesLineDisc);
if InclCampaigns then begin
InclCampaigns := TempCampaignTargetGr.Next() <> 0;
FromSalesLineDisc.SetRange("Sales Code", TempCampaignTargetGr."Campaign No.");
end;
until not InclCampaigns;
end;
OnAfterFindSalesLineDisc(
ToSalesLineDisc, CustNo, ContNo, CustDiscGrCode, CampaignNo, ItemNo, ItemDiscGrCode, VariantCode, UOM,
CurrencyCode, StartingDate, ShowAll);
end;
/// <summary>
/// Copies the temporary sales prices to the specified sales price record.
/// </summary>
/// <param name="SalesPrice">Specifies the sales price record to copy prices to.</param>
procedure CopySalesPrice(var SalesPrice: Record "Sales Price")
begin
SalesPrice.DeleteAll();
CopySalesPriceToSalesPrice(TempSalesPrice, SalesPrice);
end;
local procedure CopySalesPriceToSalesPrice(var FromSalesPrice: Record "Sales Price"; var ToSalesPrice: Record "Sales Price")
var
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeCopySalesPriceToSalesPrice(FromSalesPrice, ToSalesPrice, IsHandled);
if IsHandled then
exit;
if FromSalesPrice.FindSet() then
repeat
ToSalesPrice := FromSalesPrice;
ToSalesPrice.Insert();
until FromSalesPrice.Next() = 0;
end;
local procedure CopySalesDiscToSalesDisc(var FromSalesLineDisc: Record "Sales Line Discount"; var ToSalesLineDisc: Record "Sales Line Discount")
var
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeCopySalesLineDiscToSalesLineDisc(FromSalesLineDisc, ToSalesLineDisc, IsHandled);
if IsHandled then
exit;
if FromSalesLineDisc.FindSet() then
repeat
ToSalesLineDisc := FromSalesLineDisc;
ToSalesLineDisc.Insert();
until FromSalesLineDisc.Next() = 0;
end;
/// <summary>
/// Sets the item record used for price calculations.
/// </summary>
/// <param name="ItemNo">Specifies the item number to load.</param>
procedure SetItem(ItemNo: Code[20])
begin
Item.Get(ItemNo);
end;
/// <summary>
/// Initializes the resource price record with the specified resource code, work type, and currency.
/// </summary>
/// <param name="Code2">Specifies the resource code.</param>
/// <param name="WorkTypeCode">Specifies the work type code.</param>
/// <param name="CurrencyCode">Specifies the currency code.</param>
procedure SetResPrice(Code2: Code[20]; WorkTypeCode: Code[10]; CurrencyCode: Code[10])
begin
ResPrice.Init();
OnSetResPriceOnAfterInit(ResPrice);
ResPrice.Code := Code2;
ResPrice."Work Type Code" := WorkTypeCode;
ResPrice."Currency Code" := CurrencyCode;
end;
/// <summary>
/// Sets the currency parameters for price conversion calculations.
/// </summary>
/// <param name="CurrencyCode2">Specifies the currency code. Empty string indicates local currency.</param>
/// <param name="CurrencyFactor2">Specifies the currency exchange factor.</param>
/// <param name="ExchRateDate2">Specifies the date for the exchange rate.</param>
procedure SetCurrency(CurrencyCode2: Code[10]; CurrencyFactor2: Decimal; ExchRateDate2: Date)
begin
PricesInCurrency := CurrencyCode2 <> '';
if PricesInCurrency then begin
Currency.Get(CurrencyCode2);
Currency.TestField("Unit-Amount Rounding Precision");
CurrencyFactor := CurrencyFactor2;
ExchRateDate := ExchRateDate2;
end else
GLSetup.Get();
end;
/// <summary>
/// Sets the VAT parameters for price calculations.
/// </summary>
/// <param name="PriceInclVAT2">Specifies whether prices include VAT.</param>
/// <param name="VATPerCent2">Specifies the VAT percentage.</param>
/// <param name="VATCalcType2">Specifies the VAT calculation type.</param>
/// <param name="VATBusPostingGr2">Specifies the VAT business posting group code.</param>
procedure SetVAT(PriceInclVAT2: Boolean; VATPerCent2: Decimal; VATCalcType2: Option; VATBusPostingGr2: Code[20])
begin
PricesInclVAT := PriceInclVAT2;
VATPerCent := VATPerCent2;
VATCalcType := VATCalcType2;
VATBusPostingGr := VATBusPostingGr2;
end;
/// <summary>
/// Sets the quantity and unit of measure parameters for price calculations.
/// </summary>
/// <param name="Qty2">Specifies the quantity.</param>
/// <param name="QtyPerUoM2">Specifies the quantity per unit of measure.</param>
procedure SetUoM(Qty2: Decimal; QtyPerUoM2: Decimal)
begin
Qty := Qty2;
QtyPerUOM := QtyPerUoM2;
end;
/// <summary>
/// Sets the line discount parameters for price calculations.
/// </summary>
/// <param name="LineDiscPerCent2">Specifies the line discount percentage.</param>
/// <param name="AllowLineDisc2">Specifies whether line discount is allowed.</param>
/// <param name="AllowInvDisc2">Specifies whether invoice discount is allowed.</param>
procedure SetLineDisc(LineDiscPerCent2: Decimal; AllowLineDisc2: Boolean; AllowInvDisc2: Boolean)
begin
LineDiscPerCent := LineDiscPerCent2;
AllowLineDisc := AllowLineDisc2;
AllowInvDisc := AllowInvDisc2;
end;
local procedure SetBillToCustomerDependingOnBillingMethod(Job: Record "Job"; JobNo: Code[20]; JobTaskNo: Code[20]; var BillToCustomerNo: Code[20]; var BillToContactNo: Code[20])
var
JobTask: Record "Job Task";
begin
BillToCustomerNo := Job."Bill-to Customer No.";
BillToContactNo := Job."Bill-to Contact No.";
if Job."Task Billing Method" = Job."Task Billing Method"::"One customer" then
exit;
JobTask.Get(JobNo, JobTaskNo);
if (JobTask."Bill-to Customer No." <> '') and (JobTask."Bill-to Customer No." <> Job."Bill-to Customer No.") then begin
BillToCustomerNo := JobTask."Bill-to Customer No.";
BillToContactNo := JobTask."Bill-to Contact No.";
end;
end;
local procedure IsInMinQty(UnitofMeasureCode: Code[10]; MinQty: Decimal): Boolean
begin
if UnitofMeasureCode = '' then
exit(MinQty <= QtyPerUOM * Qty);
exit(MinQty <= Qty);
end;
/// <summary>
/// Converts a unit price between VAT-inclusive and VAT-exclusive amounts based on the VAT posting setup.
/// </summary>
/// <param name="FromPricesInclVAT">Specifies whether the source price includes VAT.</param>
/// <param name="FromVATProdPostingGr">Specifies the source VAT product posting group.</param>
/// <param name="FromVATBusPostingGr">Specifies the source VAT business posting group.</param>
/// <param name="UnitPrice">Specifies the unit price to convert. Returns the converted price.</param>
procedure ConvertPriceToVAT(FromPricesInclVAT: Boolean; FromVATProdPostingGr: Code[20]; FromVATBusPostingGr: Code[20]; var UnitPrice: Decimal)
var
VATPostingSetup: Record "VAT Posting Setup";
IsHandled: Boolean;
begin
if FromPricesInclVAT then begin
VATPostingSetup.Get(FromVATBusPostingGr, FromVATProdPostingGr);
IsHandled := false;
OnBeforeConvertPriceToVAT(VATPostingSetup, UnitPrice, IsHandled);
if IsHandled then
exit;
case VATPostingSetup."VAT Calculation Type" of
VATPostingSetup."VAT Calculation Type"::"Reverse Charge VAT":
VATPostingSetup."VAT %" := 0;
VATPostingSetup."VAT Calculation Type"::"Sales Tax":
Error(
Text010,
VATPostingSetup.FieldCaption("VAT Calculation Type"),
VATPostingSetup."VAT Calculation Type");
end;
case VATCalcType of
VATCalcType::"Normal VAT",
VATCalcType::"Full VAT",
VATCalcType::"Sales Tax":
if PricesInclVAT then begin
if VATBusPostingGr <> FromVATBusPostingGr then
UnitPrice := UnitPrice * (100 + VATPerCent) / (100 + VATPostingSetup."VAT %");
end else
UnitPrice := UnitPrice / (1 + VATPostingSetup."VAT %" / 100);
VATCalcType::"Reverse Charge VAT":
UnitPrice := UnitPrice / (1 + VATPostingSetup."VAT %" / 100);
end;
end else
if PricesInclVAT then
UnitPrice := UnitPrice * (1 + VATPerCent / 100);
end;
local procedure ConvertPriceToUoM(UnitOfMeasureCode: Code[10]; var UnitPrice: Decimal)
begin
if UnitOfMeasureCode = '' then
UnitPrice := UnitPrice * QtyPerUOM;
end;
/// <summary>
/// Converts a unit price from local currency to foreign currency if applicable, applying proper rounding.
/// </summary>
/// <param name="CurrencyCode">Specifies the currency code of the source price.</param>
/// <param name="UnitPrice">Specifies the unit price to convert. Returns the converted and rounded price.</param>
procedure ConvertPriceLCYToFCY(CurrencyCode: Code[10]; var UnitPrice: Decimal)
var
CurrExchRate: Record "Currency Exchange Rate";
begin
if PricesInCurrency then begin
if CurrencyCode = '' then
UnitPrice :=
CurrExchRate.ExchangeAmtLCYToFCY(ExchRateDate, Currency.Code, UnitPrice, CurrencyFactor);
UnitPrice := Round(UnitPrice, Currency."Unit-Amount Rounding Precision");
end else
UnitPrice := Round(UnitPrice, GLSetup."Unit-Amount Rounding Precision");
end;
local procedure CalcLineAmount(SalesPrice: Record "Sales Price") LineAmount: Decimal
begin
if SalesPrice."Allow Line Disc." then
LineAmount := SalesPrice."Unit Price" * (1 - LineDiscPerCent / 100)
else
LineAmount := SalesPrice."Unit Price";
OnAfterCalcLineAmount(SalesPrice, LineAmount, LineDiscPerCent);
end;
/// <summary>
/// Opens a lookup page to allow the user to select a sales price for the sales line.
/// </summary>
/// <param name="SalesHeader">Specifies the sales header containing customer and currency information.</param>
/// <param name="SalesLine">Specifies the sales line to apply the selected price to.</param>
procedure GetSalesLinePrice(SalesHeader: Record "Sales Header"; var SalesLine: Record "Sales Line")
var
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeGetSalesLinePrice(SalesHeader, SalesLine, IsHandled);
if IsHandled then
exit;
SalesLinePriceExists(SalesHeader, SalesLine, true);
if PAGE.RunModal(PAGE::"Get Sales Price", TempSalesPrice) = ACTION::LookupOK then begin
SetVAT(
SalesHeader."Prices Including VAT", SalesLine."VAT %", SalesLine."VAT Calculation Type".AsInteger(), SalesLine."VAT Bus. Posting Group");
SetUoM(Abs(SalesLine.Quantity), SalesLine."Qty. per Unit of Measure");
SetCurrency(
SalesHeader."Currency Code", SalesHeader."Currency Factor", SalesHeaderExchDate(SalesHeader));
if not IsInMinQty(TempSalesPrice."Unit of Measure Code", TempSalesPrice."Minimum Quantity") then
Error(
Text000,
SalesLine.FieldCaption(Quantity),
TempSalesPrice.FieldCaption("Minimum Quantity"),
TempSalesPrice.TableCaption());
if not (TempSalesPrice."Currency Code" in [SalesLine."Currency Code", '']) then
Error(
Text001,
SalesLine.FieldCaption("Currency Code"),
SalesLine.TableCaption,
TempSalesPrice.TableCaption());
if not (TempSalesPrice."Unit of Measure Code" in [SalesLine."Unit of Measure Code", '']) then
Error(
Text001,
SalesLine.FieldCaption("Unit of Measure Code"),
SalesLine.TableCaption,
TempSalesPrice.TableCaption());
if TempSalesPrice."Starting Date" > SalesHeaderStartDate(SalesHeader, DateCaption) then
Error(
Text000,
DateCaption,
TempSalesPrice.FieldCaption("Starting Date"),
TempSalesPrice.TableCaption());
ConvertPriceToVAT(
TempSalesPrice."Price Includes VAT", Item."VAT Prod. Posting Group",
TempSalesPrice."VAT Bus. Posting Gr. (Price)", TempSalesPrice."Unit Price");
ConvertPriceToUoM(TempSalesPrice."Unit of Measure Code", TempSalesPrice."Unit Price");
ConvertPriceLCYToFCY(TempSalesPrice."Currency Code", TempSalesPrice."Unit Price");
SalesLine."Allow Invoice Disc." := TempSalesPrice."Allow Invoice Disc.";
SalesLine."Allow Line Disc." := TempSalesPrice."Allow Line Disc.";
if not SalesLine."Allow Line Disc." then
SalesLine."Line Discount %" := 0;
SalesLine.Validate("Unit Price", TempSalesPrice."Unit Price");
end;
OnAfterGetSalesLinePrice(SalesHeader, SalesLine, TempSalesPrice);
end;
/// <summary>
/// Opens a lookup page to allow the user to select a line discount for the sales line.
/// </summary>
/// <param name="SalesHeader">Specifies the sales header containing customer information.</param>
/// <param name="SalesLine">Specifies the sales line to apply the selected discount to.</param>
procedure GetSalesLineLineDisc(SalesHeader: Record "Sales Header"; var SalesLine: Record "Sales Line")
var
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeGetSalesLineLineDisc(SalesHeader, SalesLine, IsHandled);
if IsHandled then
exit;
SalesLineLineDiscExists(SalesHeader, SalesLine, true);
if PAGE.RunModal(PAGE::"Get Sales Line Disc.", TempSalesLineDisc) = ACTION::LookupOK then begin
SetCurrency(SalesHeader."Currency Code", 0, 0D);
SetUoM(Abs(SalesLine.Quantity), SalesLine."Qty. per Unit of Measure");
if not IsInMinQty(TempSalesLineDisc."Unit of Measure Code", TempSalesLineDisc."Minimum Quantity")
then
Error(
Text000, SalesLine.FieldCaption(Quantity),
TempSalesLineDisc.FieldCaption("Minimum Quantity"),
TempSalesLineDisc.TableCaption());
if not (TempSalesLineDisc."Currency Code" in [SalesLine."Currency Code", '']) then
Error(
Text001,
SalesLine.FieldCaption("Currency Code"),
SalesLine.TableCaption,
TempSalesLineDisc.TableCaption());
if not (TempSalesLineDisc."Unit of Measure Code" in [SalesLine."Unit of Measure Code", '']) then
Error(
Text001,
SalesLine.FieldCaption("Unit of Measure Code"),
SalesLine.TableCaption,
TempSalesLineDisc.TableCaption());
if TempSalesLineDisc."Starting Date" > SalesHeaderStartDate(SalesHeader, DateCaption) then
Error(
Text000,
DateCaption,
TempSalesLineDisc.FieldCaption("Starting Date"),
TempSalesLineDisc.TableCaption());
SalesLine.TestField("Allow Line Disc.");
ValidateLineDiscountOnSalesLine(SalesLine);
end;
OnAfterGetSalesLineLineDisc(SalesLine, TempSalesLineDisc);
end;
local procedure ValidateLineDiscountOnSalesLine(var SalesLine: Record "Sales Line")
var
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeValidateLineDiscountOnSalesLine(SalesLine, TempSalesLineDisc, IsHandled);
if IsHandled then
exit;
SalesLine.Validate("Line Discount %", TempSalesLineDisc."Line Discount %");
end;
/// <summary>
/// Checks whether any sales prices exist for the specified sales line.
/// </summary>
/// <param name="SalesHeader">Specifies the sales header containing customer and currency information.</param>
/// <param name="SalesLine">Specifies the sales line to check prices for.</param>
/// <param name="ShowAll">Specifies whether to show all prices or only applicable ones.</param>
/// <returns>True if any sales prices exist; otherwise, false.</returns>
procedure SalesLinePriceExists(var SalesHeader: Record "Sales Header"; var SalesLine: Record "Sales Line"; ShowAll: Boolean) Result: Boolean
var
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeSalesLinePriceExistsProcedure(SalesHeader, SalesLine, ShowAll, TempSalesPrice, Result, IsHandled);
if IsHandled then
exit(Result);
if (SalesLine.Type = SalesLine.Type::Item) and Item.Get(SalesLine."No.") then begin
IsHandled := false;
OnBeforeSalesLinePriceExists(
SalesLine, SalesHeader, TempSalesPrice, Currency, CurrencyFactor,
SalesHeaderStartDate(SalesHeader, DateCaption), Qty, QtyPerUOM, ShowAll, IsHandled, this);
if not IsHandled then begin
FindSalesPrice(
TempSalesPrice, GetCustNoForSalesHeader(SalesHeader), SalesHeader."Bill-to Contact No.",
SalesLine."Customer Price Group", '', SalesLine."No.", SalesLine."Variant Code", SalesLine."Unit of Measure Code",
SalesHeader."Currency Code", SalesHeaderStartDate(SalesHeader, DateCaption), ShowAll);
OnAfterSalesLinePriceExists(SalesLine, SalesHeader, TempSalesPrice, ShowAll);
end;
exit(TempSalesPrice.FindFirst());
end;
Result := false;
OnAfterSalesLinePriceExistsProcedure(SalesHeader, SalesLine, Res, DateCaption, ShowAll, Result);
end;
/// <summary>
/// Checks whether any sales line discounts exist for the specified sales line.
/// </summary>
/// <param name="SalesHeader">Specifies the sales header containing customer information.</param>
/// <param name="SalesLine">Specifies the sales line to check discounts for.</param>
/// <param name="ShowAll">Specifies whether to show all discounts or only applicable ones.</param>
/// <returns>True if any sales line discounts exist; otherwise, false.</returns>
procedure SalesLineLineDiscExists(var SalesHeader: Record "Sales Header"; var SalesLine: Record "Sales Line"; ShowAll: Boolean): Boolean
var
IsHandled: Boolean;
begin
if (SalesLine.Type = SalesLine.Type::Item) and Item.Get(SalesLine."No.") then begin
IsHandled := false;
OnBeforeSalesLineLineDiscExists(
SalesLine, SalesHeader, TempSalesLineDisc, SalesHeaderStartDate(SalesHeader, DateCaption),
Qty, QtyPerUOM, ShowAll, IsHandled, this);
if not IsHandled then begin
FindSalesLineDisc(
TempSalesLineDisc, GetCustNoForSalesHeader(SalesHeader), SalesHeader."Bill-to Contact No.",
SalesLine."Customer Disc. Group", '', SalesLine."No.", Item."Item Disc. Group", SalesLine."Variant Code", SalesLine."Unit of Measure Code",
SalesHeader."Currency Code", SalesHeaderStartDate(SalesHeader, DateCaption), ShowAll);
OnAfterSalesLineLineDiscExists(SalesLine, SalesHeader, TempSalesLineDisc, ShowAll);
end;
exit(TempSalesLineDisc.FindFirst())
end;
exit(false);
end;
#if not CLEAN28
/// <summary>
/// Gets the sales price for a service line.
/// </summary>
/// <param name="ServHeader">The service header containing customer information.</param>
/// <param name="ServLine">The service line to get the price for.</param>
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
procedure GetServLinePrice(ServHeader: Record Microsoft.Service.Document."Service Header"; var ServLine: Record Microsoft.Service.Document."Service Line")
begin
ServPriceCalcMgt.GetServLinePrice(ServHeader, ServLine);
end;
#endif
#if not CLEAN28
/// <summary>
/// Gets the line discount for a service line.
/// </summary>
/// <param name="ServHeader">The service header containing customer information.</param>
/// <param name="ServLine">The service line to get the discount for.</param>
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
procedure GetServLineLineDisc(ServHeader: Record Microsoft.Service.Document."Service Header"; var ServLine: Record Microsoft.Service.Document."Service Line")
begin
ServPriceCalcMgt.GetServLineLineDisc(ServHeader, ServLine);
end;
#endif
local procedure GetCustNoForSalesHeader(SalesHeader: Record "Sales Header"): Code[20]
var
CustNo: Code[20];
begin
CustNo := SalesHeader."Bill-to Customer No.";
OnGetCustNoForSalesHeader(SalesHeader, CustNo);
exit(CustNo);
end;
#if not CLEAN28
/// <summary>
/// Checks whether any sales prices exist for the service line.
/// </summary>
/// <param name="ServHeader">The service header containing customer information.</param>
/// <param name="ServLine">The service line to check prices for.</param>
/// <param name="ShowAll">Specifies whether to show all prices or only the best price.</param>
/// <returns>True if sales prices exist for the service line, otherwise false.</returns>
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
[Scope('OnPrem')]
procedure ServLinePriceExists(ServHeader: Record Microsoft.Service.Document."Service Header"; var ServLine: Record Microsoft.Service.Document."Service Line"; ShowAll: Boolean): Boolean
var
IsHandled: Boolean;
begin
exit(ServPriceCalcMgt.ServLinePriceExists(ServHeader, ServLine, ShowAll));
end;
#endif
#if not CLEAN28
/// <summary>
/// Checks whether any line discounts exist for the service line.
/// </summary>
/// <param name="ServHeader">The service header containing customer information.</param>
/// <param name="ServLine">The service line to check discounts for.</param>
/// <param name="ShowAll">Specifies whether to show all discounts or only the best discount.</param>
/// <returns>True if line discounts exist for the service line, otherwise false.</returns>
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
[Scope('OnPrem')]
procedure ServLineLineDiscExists(ServHeader: Record Microsoft.Service.Document."Service Header"; var ServLine: Record Microsoft.Service.Document."Service Line"; ShowAll: Boolean): Boolean
begin
exit(ServLineLineDiscExists(ServHeader, ServLine, ShowAll));
end;
#endif
/// <summary>
/// Checks whether any activated campaigns exist for the specified customer, contact, or campaign number.
/// </summary>
/// <param name="ToCampaignTargetGr">Returns the temporary campaign target group records found.</param>
/// <param name="CustNo">Specifies the customer number to search campaigns for.</param>
/// <param name="ContNo">Specifies the contact number to search campaigns for.</param>
/// <param name="CampaignNo">Specifies the campaign number to search for.</param>
/// <returns>True if any activated campaigns exist; otherwise, false.</returns>
procedure ActivatedCampaignExists(var ToCampaignTargetGr: Record "Campaign Target Group"; CustNo: Code[20]; ContNo: Code[20]; CampaignNo: Code[20]): Boolean
var
FromCampaignTargetGr: Record "Campaign Target Group";
Cont: Record Contact;
IsHandled: Boolean;
begin
if not ToCampaignTargetGr.IsTemporary then
Error(TempTableErr);
IsHandled := false;
OnBeforeActivatedCampaignExists(ToCampaignTargetGr, CustNo, ContNo, CampaignNo, IsHandled);
if IsHandled then
exit;
ToCampaignTargetGr.Reset();
ToCampaignTargetGr.DeleteAll();
if CampaignNo <> '' then begin
ToCampaignTargetGr."Campaign No." := CampaignNo;
ToCampaignTargetGr.Insert();
end else begin
FromCampaignTargetGr.SetRange(Type, FromCampaignTargetGr.Type::Customer);
FromCampaignTargetGr.SetRange("No.", CustNo);
if FromCampaignTargetGr.FindSet() then
repeat
ToCampaignTargetGr := FromCampaignTargetGr;
ToCampaignTargetGr.Insert();
until FromCampaignTargetGr.Next() = 0
else
if Cont.Get(ContNo) then begin
FromCampaignTargetGr.SetRange(Type, FromCampaignTargetGr.Type::Contact);
FromCampaignTargetGr.SetRange("No.", Cont."Company No.");
if FromCampaignTargetGr.FindSet() then
repeat
ToCampaignTargetGr := FromCampaignTargetGr;
ToCampaignTargetGr.Insert();
until FromCampaignTargetGr.Next() = 0;
end;
end;
exit(ToCampaignTargetGr.FindFirst())
end;
/// <summary>
/// Returns the exchange rate date to use for currency conversion based on the sales header.
/// </summary>
/// <param name="SalesHeader">Specifies the sales header to get the exchange date from.</param>
/// <returns>The posting date if specified; otherwise, the work date.</returns>
procedure SalesHeaderExchDate(SalesHeader: Record "Sales Header"): Date
begin
if SalesHeader."Posting Date" <> 0D then
exit(SalesHeader."Posting Date");
exit(WorkDate());
end;
/// <summary>
/// Returns the starting date to use for price lookups based on the sales header document type.
/// </summary>
/// <param name="SalesHeader">Specifies the sales header to get the start date from.</param>
/// <param name="DateCaption">Returns the caption of the date field used.</param>
/// <returns>The posting date for invoices and credit memos; the order date for other document types.</returns>
procedure SalesHeaderStartDate(var SalesHeader: Record "Sales Header"; var DateCaption: Text[30]): Date
var
StartDate: Date;
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeSalesHeaderStartDate(SalesHeader, DateCaption, StartDate, IsHandled);
if IsHandled then
exit(StartDate);
if SalesHeader."Document Type" in [SalesHeader."Document Type"::Invoice, SalesHeader."Document Type"::"Credit Memo"] then begin
DateCaption := SalesHeader.FieldCaption("Posting Date");
exit(SalesHeader."Posting Date")
end else begin
DateCaption := SalesHeader.FieldCaption("Order Date");
exit(SalesHeader."Order Date");
end;
end;
#if not CLEAN28
/// <summary>
/// Returns the exchange rate date to use for currency conversion based on the service header.
/// </summary>
/// <param name="ServHeader">The service header to get the exchange date from.</param>
/// <returns>The posting date if specified, otherwise the work date.</returns>
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
procedure ServHeaderExchDate(ServHeader: Record Microsoft.Service.Document."Service Header"): Date
begin
exit(ServPriceCalcMgt.ServHeaderExchDate(ServHeader));
end;
#endif
#if not CLEAN28
/// <summary>
/// Returns the starting date to use for price lookups based on the service header.
/// </summary>
/// <param name="ServHeader">The service header to get the start date from.</param>
/// <param name="DateCaption">Returns the caption of the date field used.</param>
/// <returns>The appropriate date for price calculations.</returns>
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
procedure ServHeaderStartDate(ServHeader: Record Microsoft.Service.Document."Service Header"; var DateCaption: Text[30]): Date
begin
exit(ServPriceCalcMgt.ServHeaderStartDate(ServHeader, DateCaption));
end;
#endif
/// <summary>
/// Returns the number of sales prices available for the specified sales line.
/// </summary>
/// <param name="SalesHeader">Specifies the sales header containing customer and currency information.</param>
/// <param name="SalesLine">Specifies the sales line to count prices for.</param>
/// <param name="ShowAll">Specifies whether to count all prices or only applicable ones.</param>
/// <returns>The number of available sales prices.</returns>
procedure NoOfSalesLinePrice(var SalesHeader: Record "Sales Header"; var SalesLine: Record "Sales Line"; ShowAll: Boolean) Result: Integer
var
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeNoOfSalesLinePrice(SalesHeader, SalesLine, ShowAll, Result, IsHandled);
if IsHandled then
exit(Result);
if SalesLinePriceExists(SalesHeader, SalesLine, ShowAll) then
exit(TempSalesPrice.Count);
end;
/// <summary>
/// Returns the number of sales line discounts available for the specified sales line.
/// </summary>
/// <param name="SalesHeader">Specifies the sales header containing customer information.</param>
/// <param name="SalesLine">Specifies the sales line to count discounts for.</param>
/// <param name="ShowAll">Specifies whether to count all discounts or only applicable ones.</param>
/// <returns>The number of available sales line discounts.</returns>
procedure NoOfSalesLineLineDisc(var SalesHeader: Record "Sales Header"; var SalesLine: Record "Sales Line"; ShowAll: Boolean) Result: Integer
var
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeNoOfSalesLineLineDisc(SalesHeader, SalesLine, ShowAll, Result, IsHandled);
if IsHandled then
exit(Result);
if SalesLineLineDiscExists(SalesHeader, SalesLine, ShowAll) then
exit(TempSalesLineDisc.Count);
end;
#if not CLEAN28
/// <summary>
/// Returns the number of sales prices available for the specified service line.
/// </summary>
/// <param name="ServHeader">The service header containing customer and currency information.</param>
/// <param name="ServLine">The service line to count prices for.</param>
/// <param name="ShowAll">Specifies whether to count all prices or only applicable ones.</param>
/// <returns>The number of available sales prices.</returns>
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
procedure NoOfServLinePrice(ServHeader: Record Microsoft.Service.Document."Service Header"; var ServLine: Record Microsoft.Service.Document."Service Line"; ShowAll: Boolean) Result: Integer
begin
exit(ServPriceCalcMgt.NoOfServLinePrice(ServHeader, ServLine, ShowAll));
end;
#endif
#if not CLEAN28
/// <summary>
/// Returns the number of sales line discounts available for the specified service line.
/// </summary>
/// <param name="ServHeader">The service header containing customer information.</param>
/// <param name="ServLine">The service line to count discounts for.</param>
/// <param name="ShowAll">Specifies whether to count all discounts or only applicable ones.</param>
/// <returns>The number of available sales line discounts.</returns>
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
procedure NoOfServLineLineDisc(ServHeader: Record Microsoft.Service.Document."Service Header"; var ServLine: Record Microsoft.Service.Document."Service Line"; ShowAll: Boolean) Result: Integer
begin
exit(ServPriceCalcMgt.NoOfServLineLineDisc(ServHeader, ServLine, ShowAll));
end;
#endif
/// <summary>
/// Finds and applies the best price for a job planning line based on customer, item, and resource pricing.
/// </summary>
/// <param name="JobPlanningLine">Specifies the job planning line to calculate the price for.</param>
/// <param name="CalledByFieldNo">Specifies the field number that triggered the price calculation.</param>
procedure FindJobPlanningLinePrice(var JobPlanningLine: Record "Job Planning Line"; CalledByFieldNo: Integer)
var
Job: Record Job;
BillToCustomerNo, BillToContactNo : Code[20];
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeFindJobPlanningLinePrice(JobPlanningLine, CalledByFieldNo, IsHandled);
if IsHandled then
exit;
SetCurrency(JobPlanningLine."Currency Code", JobPlanningLine."Currency Factor", JobPlanningLine."Planning Date");
SetVAT(false, 0, 0, '');
SetUoM(Abs(JobPlanningLine.Quantity), JobPlanningLine."Qty. per Unit of Measure");
SetLineDisc(0, true, true);
case JobPlanningLine.Type of
JobPlanningLine.Type::Item:
begin
Job.Get(JobPlanningLine."Job No.");
Item.Get(JobPlanningLine."No.");
JobPlanningLine.TestField("Qty. per Unit of Measure");
SetBillToCustomerDependingOnBillingMethod(Job, JobPlanningLine."Job No.", JobPlanningLine."Job Task No.", BillToCustomerNo, BillToContactNo);
FindSalesPrice(
TempSalesPrice, BillToCustomerNo, BillToContactNo,
Job."Customer Price Group", '', JobPlanningLine."No.", JobPlanningLine."Variant Code", JobPlanningLine."Unit of Measure Code",
Job."Currency Code", JobPlanningLine."Planning Date", false);
CalcBestUnitPrice(TempSalesPrice);
if FoundSalesPrice or
not ((CalledByFieldNo = JobPlanningLine.FieldNo(Quantity)) or
(CalledByFieldNo = JobPlanningLine.FieldNo("Location Code")) or
(CalledByFieldNo = JobPlanningLine.FieldNo("Variant Code")))
then begin
JobPlanningLine."Unit Price" := TempSalesPrice."Unit Price";
AllowLineDisc := TempSalesPrice."Allow Line Disc.";
end;
end;
JobPlanningLine.Type::Resource:
begin
Job.Get(JobPlanningLine."Job No.");
SetResPrice(JobPlanningLine."No.", JobPlanningLine."Work Type Code", JobPlanningLine."Currency Code");
CODEUNIT.Run(CODEUNIT::"Resource-Find Price", ResPrice);
IsHandled := false;
OnAfterFindJobPlanningLineResPrice(JobPlanningLine, ResPrice, CalledByFieldNo, AllowLineDisc, IsHandled);
if not IsHandled then begin
ConvertPriceLCYToFCY(ResPrice."Currency Code", ResPrice."Unit Price");
JobPlanningLine."Unit Price" := ResPrice."Unit Price" * JobPlanningLine."Qty. per Unit of Measure";
end;
end;
end;
OnFindJobPlanningLinePriceOnBeforeJobPlanningLineFindJTPrice(JobPlanningLine, ResPrice);
JobPlanningLineFindJTPrice(JobPlanningLine);
end;
/// <summary>
/// Finds and applies job-specific prices for a job planning line based on job item prices, resource prices, or G/L account prices.
/// </summary>
/// <param name="JobPlanningLine">Specifies the job planning line to find job-specific prices for.</param>
procedure JobPlanningLineFindJTPrice(var JobPlanningLine: Record "Job Planning Line")
var
JobItemPrice: Record "Job Item Price";
JobResPrice: Record "Job Resource Price";
JobGLAccPrice: Record "Job G/L Account Price";
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeJobPlanningLineFindJTPrice(JobPlanningLine, IsHandled);
if IsHandled then
exit;
case JobPlanningLine.Type of
JobPlanningLine.Type::Item:
begin
JobItemPrice.SetRange("Job No.", JobPlanningLine."Job No.");
JobItemPrice.SetRange("Item No.", JobPlanningLine."No.");
JobItemPrice.SetRange("Variant Code", JobPlanningLine."Variant Code");
JobItemPrice.SetRange("Unit of Measure Code", JobPlanningLine."Unit of Measure Code");
JobItemPrice.SetRange("Currency Code", JobPlanningLine."Currency Code");
JobItemPrice.SetRange("Job Task No.", JobPlanningLine."Job Task No.");
OnJobPlanningLineFindJTPriceOnAfterSetJobItemPriceFilters(JobItemPrice, JobPlanningLine);
if JobItemPrice.FindFirst() then
CopyJobItemPriceToJobPlanLine(JobPlanningLine, JobItemPrice)
else begin
JobItemPrice.SetRange("Job Task No.", ' ');
if JobItemPrice.FindFirst() then
CopyJobItemPriceToJobPlanLine(JobPlanningLine, JobItemPrice);
end;
if JobItemPrice.IsEmpty() or (not JobItemPrice."Apply Job Discount") then
FindJobPlanningLineLineDisc(JobPlanningLine);
end;
JobPlanningLine.Type::Resource:
begin
Res.Get(JobPlanningLine."No.");
JobResPrice.SetRange("Job No.", JobPlanningLine."Job No.");
JobResPrice.SetRange("Currency Code", JobPlanningLine."Currency Code");
JobResPrice.SetRange("Job Task No.", JobPlanningLine."Job Task No.");
OnJobPlanningLineFindJTPriceOnAfterSetJobResPriceFilters(JobResPrice, JobPlanningLine);
case true of
JobPlanningLineFindJobResPrice(JobPlanningLine, JobResPrice, JobResPrice.Type::Resource):
CopyJobResPriceToJobPlanLine(JobPlanningLine, JobResPrice);
JobPlanningLineFindJobResPrice(JobPlanningLine, JobResPrice, JobResPrice.Type::"Group(Resource)"):
CopyJobResPriceToJobPlanLine(JobPlanningLine, JobResPrice);
JobPlanningLineFindJobResPrice(JobPlanningLine, JobResPrice, JobResPrice.Type::All):
CopyJobResPriceToJobPlanLine(JobPlanningLine, JobResPrice);
else begin
JobResPrice.SetRange("Job Task No.", '');
case true of
JobPlanningLineFindJobResPrice(JobPlanningLine, JobResPrice, JobResPrice.Type::Resource):
CopyJobResPriceToJobPlanLine(JobPlanningLine, JobResPrice);
JobPlanningLineFindJobResPrice(JobPlanningLine, JobResPrice, JobResPrice.Type::"Group(Resource)"):
CopyJobResPriceToJobPlanLine(JobPlanningLine, JobResPrice);
JobPlanningLineFindJobResPrice(JobPlanningLine, JobResPrice, JobResPrice.Type::All):
CopyJobResPriceToJobPlanLine(JobPlanningLine, JobResPrice);
end;
end;
end;
end;
JobPlanningLine.Type::"G/L Account":
begin
JobGLAccPrice.SetRange("Job No.", JobPlanningLine."Job No.");
JobGLAccPrice.SetRange("G/L Account No.", JobPlanningLine."No.");
JobGLAccPrice.SetRange("Currency Code", JobPlanningLine."Currency Code");
JobGLAccPrice.SetRange("Job Task No.", JobPlanningLine."Job Task No.");
OnJobPlanningLineFindJTPriceOnAfterSetJobGLAccPriceFilters(JobGLAccPrice, JobPlanningLine);
if JobGLAccPrice.FindFirst() then
CopyJobGLAccPriceToJobPlanLine(JobPlanningLine, JobGLAccPrice)
else begin
JobGLAccPrice.SetRange("Job Task No.", '');
if JobGLAccPrice.FindFirst() then
CopyJobGLAccPriceToJobPlanLine(JobPlanningLine, JobGLAccPrice);
end;
end;
end;
end;
local procedure CopyJobItemPriceToJobPlanLine(var JobPlanningLine: Record "Job Planning Line"; JobItemPrice: Record "Job Item Price")
var
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeCopyJobItemPriceToJobPlanLine(JobPlanningLine, JobItemPrice, IsHandled);
if IsHandled then
exit;
if JobItemPrice."Apply Job Price" then begin
JobPlanningLine."Unit Price" := JobItemPrice."Unit Price";
JobPlanningLine."Cost Factor" := JobItemPrice."Unit Cost Factor";
end;
if JobItemPrice."Apply Job Discount" then
JobPlanningLine."Line Discount %" := JobItemPrice."Line Discount %";
end;
local procedure CopyJobResPriceToJobPlanLine(var JobPlanningLine: Record "Job Planning Line"; JobResPrice: Record "Job Resource Price")
begin
if JobResPrice."Apply Job Price" then begin
JobPlanningLine."Unit Price" := JobResPrice."Unit Price" * JobPlanningLine."Qty. per Unit of Measure";
JobPlanningLine."Cost Factor" := JobResPrice."Unit Cost Factor";
end;
if JobResPrice."Apply Job Discount" then
JobPlanningLine."Line Discount %" := JobResPrice."Line Discount %";
end;
local procedure JobPlanningLineFindJobResPrice(var JobPlanningLine: Record "Job Planning Line"; var JobResPrice: Record "Job Resource Price"; PriceType: Option Resource,"Group(Resource)",All): Boolean
begin
case PriceType of
PriceType::Resource:
begin
JobResPrice.SetRange(Type, JobResPrice.Type::Resource);
JobResPrice.SetRange("Work Type Code", JobPlanningLine."Work Type Code");
JobResPrice.SetRange(Code, JobPlanningLine."No.");
exit(JobResPrice.Find('-'));
end;
PriceType::"Group(Resource)":
begin
JobResPrice.SetRange(Type, JobResPrice.Type::"Group(Resource)");
JobResPrice.SetRange(Code, Res."Resource Group No.");
exit(FindJobResPrice(JobResPrice, JobPlanningLine."Work Type Code"));
end;
PriceType::All:
begin
JobResPrice.SetRange(Type, JobResPrice.Type::All);
JobResPrice.SetRange(Code);
exit(FindJobResPrice(JobResPrice, JobPlanningLine."Work Type Code"));
end;
end;
end;
local procedure CopyJobGLAccPriceToJobPlanLine(var JobPlanningLine: Record "Job Planning Line"; JobGLAccPrice: Record "Job G/L Account Price")
begin
JobPlanningLine."Unit Cost" := JobGLAccPrice."Unit Cost";
JobPlanningLine."Unit Price" := JobGLAccPrice."Unit Price" * JobPlanningLine."Qty. per Unit of Measure";
JobPlanningLine."Cost Factor" := JobGLAccPrice."Unit Cost Factor";
JobPlanningLine."Line Discount %" := JobGLAccPrice."Line Discount %";
end;
/// <summary>
/// Finds and applies the best price for a job journal line based on customer, item, and resource pricing.
/// </summary>
/// <param name="JobJnlLine">Specifies the job journal line to calculate the price for.</param>
/// <param name="CalledByFieldNo">Specifies the field number that triggered the price calculation.</param>
procedure FindJobJnlLinePrice(var JobJnlLine: Record "Job Journal Line"; CalledByFieldNo: Integer)
var
Job: Record Job;
BillToCustomerNo, BillToContactNo : Code[20];
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeFindJobJnlLinePrice(JobJnlLine, CalledByFieldNo, IsHandled);
if IsHandled then
exit;
SetCurrency(JobJnlLine."Currency Code", JobJnlLine."Currency Factor", JobJnlLine."Posting Date");
SetVAT(false, 0, 0, '');
SetUoM(Abs(JobJnlLine.Quantity), JobJnlLine."Qty. per Unit of Measure");
case JobJnlLine.Type of
JobJnlLine.Type::Item:
begin
Item.Get(JobJnlLine."No.");
JobJnlLine.TestField("Qty. per Unit of Measure");
Job.Get(JobJnlLine."Job No.");
SetBillToCustomerDependingOnBillingMethod(Job, JobJnlLine."Job No.", JobJnlLine."Job Task No.", BillToCustomerNo, BillToContactNo);
FindSalesPrice(
TempSalesPrice, BillToCustomerNo, BillToContactNo,
JobJnlLine."Customer Price Group", '', JobJnlLine."No.", JobJnlLine."Variant Code", JobJnlLine."Unit of Measure Code",
JobJnlLine."Currency Code", JobJnlLine."Posting Date", false);
CalcBestUnitPrice(TempSalesPrice);
if FoundSalesPrice or
not ((CalledByFieldNo = JobJnlLine.FieldNo(Quantity)) or
(CalledByFieldNo = JobJnlLine.FieldNo("Variant Code")))
then
JobJnlLine."Unit Price" := TempSalesPrice."Unit Price";
end;
JobJnlLine.Type::Resource:
begin
IsHandled := false;
OnFindJobJnlLinePriceOnBeforeResourceGetJob(JobJnlLine, IsHandled);
if not IsHandled then
Job.Get(JobJnlLine."Job No.");
SetResPrice(JobJnlLine."No.", JobJnlLine."Work Type Code", JobJnlLine."Currency Code");
OnBeforeFindJobJnlLineResPrice(JobJnlLine, ResPrice);
CODEUNIT.Run(CODEUNIT::"Resource-Find Price", ResPrice);
IsHandled := false;
OnAfterFindJobJnlLineResPrice(JobJnlLine, ResPrice, CalledByFieldNo, IsHandled);
if not IsHandled then begin
ConvertPriceLCYToFCY(ResPrice."Currency Code", ResPrice."Unit Price");
JobJnlLine."Unit Price" := ResPrice."Unit Price" * JobJnlLine."Qty. per Unit of Measure";
end;
end;
end;
OnFindJobJnlLinePriceOnBeforeJobJnlLineFindJTPrice(JobJnlLine);
JobJnlLineFindJTPrice(JobJnlLine);
end;
local procedure JobJnlLineFindJobResPrice(var JobJnlLine: Record "Job Journal Line"; var JobResPrice: Record "Job Resource Price"; PriceType: Option Resource,"Group(Resource)",All): Boolean
begin
case PriceType of
PriceType::Resource:
begin
JobResPrice.SetRange(Type, JobResPrice.Type::Resource);
JobResPrice.SetRange("Work Type Code", JobJnlLine."Work Type Code");
JobResPrice.SetRange(Code, JobJnlLine."No.");
exit(JobResPrice.Find('-'));
end;
PriceType::"Group(Resource)":
begin
JobResPrice.SetRange(Type, JobResPrice.Type::"Group(Resource)");
JobResPrice.SetRange(Code, Res."Resource Group No.");
exit(FindJobResPrice(JobResPrice, JobJnlLine."Work Type Code"));
end;
PriceType::All:
begin
JobResPrice.SetRange(Type, JobResPrice.Type::All);
JobResPrice.SetRange(Code);
exit(FindJobResPrice(JobResPrice, JobJnlLine."Work Type Code"));
end;
end;
end;
local procedure CopyJobResPriceToJobJnlLine(var JobJnlLine: Record "Job Journal Line"; JobResPrice: Record "Job Resource Price")
begin
if JobResPrice."Apply Job Price" then begin
JobJnlLine."Unit Price" := JobResPrice."Unit Price" * JobJnlLine."Qty. per Unit of Measure";
JobJnlLine."Cost Factor" := JobResPrice."Unit Cost Factor";
end;
if JobResPrice."Apply Job Discount" then
JobJnlLine."Line Discount %" := JobResPrice."Line Discount %";
OnAfterCopyJobResPriceToJobJnlLine(JobJnlLine);
end;
local procedure CopyJobGLAccPriceToJobJnlLine(var JobJnlLine: Record "Job Journal Line"; JobGLAccPrice: Record "Job G/L Account Price")
begin
JobJnlLine."Unit Cost" := JobGLAccPrice."Unit Cost";
JobJnlLine."Unit Price" := JobGLAccPrice."Unit Price" * JobJnlLine."Qty. per Unit of Measure";
JobJnlLine."Cost Factor" := JobGLAccPrice."Unit Cost Factor";
JobJnlLine."Line Discount %" := JobGLAccPrice."Line Discount %";
end;
/// <summary>
/// Finds and applies job-specific prices for a job journal line based on job item prices, resource prices, or G/L account prices.
/// </summary>
/// <param name="JobJnlLine">Specifies the job journal line to find job-specific prices for.</param>
procedure JobJnlLineFindJTPrice(var JobJnlLine: Record "Job Journal Line")
var
JobItemPrice: Record "Job Item Price";
JobResPrice: Record "Job Resource Price";
JobGLAccPrice: Record "Job G/L Account Price";
begin
case JobJnlLine.Type of
JobJnlLine.Type::Item:
begin
JobItemPrice.SetRange("Job No.", JobJnlLine."Job No.");
JobItemPrice.SetRange("Item No.", JobJnlLine."No.");
JobItemPrice.SetRange("Variant Code", JobJnlLine."Variant Code");
JobItemPrice.SetRange("Unit of Measure Code", JobJnlLine."Unit of Measure Code");
JobItemPrice.SetRange("Currency Code", JobJnlLine."Currency Code");
JobItemPrice.SetRange("Job Task No.", JobJnlLine."Job Task No.");
OnJobJnlLineFindJTPriceOnAfterSetJobItemPriceFilters(JobItemPrice, JobJnlLine);
if JobItemPrice.FindFirst() then
CopyJobItemPriceToJobJnlLine(JobJnlLine, JobItemPrice)
else begin
JobItemPrice.SetRange("Job Task No.", ' ');
if JobItemPrice.FindFirst() then
CopyJobItemPriceToJobJnlLine(JobJnlLine, JobItemPrice);
end;
if JobItemPrice.IsEmpty() or (not JobItemPrice."Apply Job Discount") then
FindJobJnlLineLineDisc(JobJnlLine);
OnAfterJobJnlLineFindJTPriceItem(JobJnlLine);
end;
JobJnlLine.Type::Resource:
begin
Res.Get(JobJnlLine."No.");
JobResPrice.SetRange("Job No.", JobJnlLine."Job No.");
JobResPrice.SetRange("Currency Code", JobJnlLine."Currency Code");
JobResPrice.SetRange("Job Task No.", JobJnlLine."Job Task No.");
case true of
JobJnlLineFindJobResPrice(JobJnlLine, JobResPrice, JobResPrice.Type::Resource):
CopyJobResPriceToJobJnlLine(JobJnlLine, JobResPrice);
JobJnlLineFindJobResPrice(JobJnlLine, JobResPrice, JobResPrice.Type::"Group(Resource)"):
CopyJobResPriceToJobJnlLine(JobJnlLine, JobResPrice);
JobJnlLineFindJobResPrice(JobJnlLine, JobResPrice, JobResPrice.Type::All):
CopyJobResPriceToJobJnlLine(JobJnlLine, JobResPrice);
else begin
JobResPrice.SetRange("Job Task No.", '');
case true of
JobJnlLineFindJobResPrice(JobJnlLine, JobResPrice, JobResPrice.Type::Resource):
CopyJobResPriceToJobJnlLine(JobJnlLine, JobResPrice);
JobJnlLineFindJobResPrice(JobJnlLine, JobResPrice, JobResPrice.Type::"Group(Resource)"):
CopyJobResPriceToJobJnlLine(JobJnlLine, JobResPrice);
JobJnlLineFindJobResPrice(JobJnlLine, JobResPrice, JobResPrice.Type::All):
CopyJobResPriceToJobJnlLine(JobJnlLine, JobResPrice);
end;
end;
end;
OnAfterJobJnlLineFindJTPriceResource(JobJnlLine);
end;
JobJnlLine.Type::"G/L Account":
begin
JobGLAccPrice.SetRange("Job No.", JobJnlLine."Job No.");
JobGLAccPrice.SetRange("G/L Account No.", JobJnlLine."No.");
JobGLAccPrice.SetRange("Currency Code", JobJnlLine."Currency Code");
JobGLAccPrice.SetRange("Job Task No.", JobJnlLine."Job Task No.");
if JobGLAccPrice.FindFirst() then
CopyJobGLAccPriceToJobJnlLine(JobJnlLine, JobGLAccPrice)
else begin
JobGLAccPrice.SetRange("Job Task No.", '');
if JobGLAccPrice.FindFirst() then;
CopyJobGLAccPriceToJobJnlLine(JobJnlLine, JobGLAccPrice);
end;
OnAfterJobJnlLineFindJTPriceGLAccount(JobJnlLine);
end;
end;
end;
local procedure CopyJobItemPriceToJobJnlLine(var JobJnlLine: Record "Job Journal Line"; JobItemPrice: Record "Job Item Price")
var
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeCopyJobItemPriceToJobJnlLine(JobJnlLine, JobItemPrice, IsHandled);
if IsHandled then
exit;
if JobItemPrice."Apply Job Price" then begin
JobJnlLine."Unit Price" := JobItemPrice."Unit Price";
JobJnlLine."Cost Factor" := JobItemPrice."Unit Cost Factor";
end;
if JobItemPrice."Apply Job Discount" then
JobJnlLine."Line Discount %" := JobItemPrice."Line Discount %";
end;
local procedure FindJobPlanningLineLineDisc(var JobPlanningLine: Record "Job Planning Line")
begin
SetCurrency(JobPlanningLine."Currency Code", JobPlanningLine."Currency Factor", JobPlanningLine."Planning Date");
SetUoM(Abs(JobPlanningLine.Quantity), JobPlanningLine."Qty. per Unit of Measure");
JobPlanningLine.TestField("Qty. per Unit of Measure");
if JobPlanningLine.Type = JobPlanningLine.Type::Item then begin
JobPlanningLineLineDiscExists(JobPlanningLine, false);
CalcBestLineDisc(TempSalesLineDisc);
if AllowLineDisc then
JobPlanningLine."Line Discount %" := TempSalesLineDisc."Line Discount %"
else
JobPlanningLine."Line Discount %" := 0;
end;
OnAfterFindJobPlanningLineLineDisc(JobPlanningLine, TempSalesLineDisc);
end;
local procedure JobPlanningLineLineDiscExists(var JobPlanningLine: Record "Job Planning Line"; ShowAll: Boolean): Boolean
var
Job: Record Job;
begin
if (JobPlanningLine.Type = JobPlanningLine.Type::Item) and Item.Get(JobPlanningLine."No.") then begin
Job.Get(JobPlanningLine."Job No.");
OnBeforeJobPlanningLineLineDiscExists(JobPlanningLine);
FindSalesLineDisc(
TempSalesLineDisc, Job."Bill-to Customer No.", Job."Bill-to Contact No.",
Job."Customer Disc. Group", '', JobPlanningLine."No.", Item."Item Disc. Group", JobPlanningLine."Variant Code", JobPlanningLine."Unit of Measure Code",
JobPlanningLine."Currency Code", JobPlanningLineStartDate(JobPlanningLine, DateCaption), ShowAll);
OnAfterJobPlanningLineLineDiscExists(JobPlanningLine);
exit(TempSalesLineDisc.Find('-'));
end;
exit(false);
end;
local procedure JobPlanningLineStartDate(JobPlanningLine: Record "Job Planning Line"; var DateCaption: Text[30]): Date
begin
DateCaption := JobPlanningLine.FieldCaption("Planning Date");
exit(JobPlanningLine."Planning Date");
end;
local procedure FindJobJnlLineLineDisc(var JobJnlLine: Record "Job Journal Line")
begin
SetCurrency(JobJnlLine."Currency Code", JobJnlLine."Currency Factor", JobJnlLine."Posting Date");
SetUoM(Abs(JobJnlLine.Quantity), JobJnlLine."Qty. per Unit of Measure");
JobJnlLine.TestField("Qty. per Unit of Measure");
if JobJnlLine.Type = JobJnlLine.Type::Item then begin
JobJnlLineLineDiscExists(JobJnlLine, false);
CalcBestLineDisc(TempSalesLineDisc);
JobJnlLine."Line Discount %" := TempSalesLineDisc."Line Discount %";
end;
OnAfterFindJobJnlLineLineDisc(JobJnlLine, TempSalesLineDisc);
end;
local procedure JobJnlLineLineDiscExists(var JobJnlLine: Record "Job Journal Line"; ShowAll: Boolean): Boolean
var
Job: Record Job;
begin
if (JobJnlLine.Type = JobJnlLine.Type::Item) and Item.Get(JobJnlLine."No.") then begin
Job.Get(JobJnlLine."Job No.");
OnBeforeJobJnlLineLineDiscExists(JobJnlLine);
FindSalesLineDisc(
TempSalesLineDisc, Job."Bill-to Customer No.", Job."Bill-to Contact No.",
Job."Customer Disc. Group", '', JobJnlLine."No.", Item."Item Disc. Group", JobJnlLine."Variant Code", JobJnlLine."Unit of Measure Code",
JobJnlLine."Currency Code", JobJnlLineStartDate(JobJnlLine, DateCaption), ShowAll);
OnAfterJobJnlLineLineDiscExists(JobJnlLine);
exit(TempSalesLineDisc.Find('-'));
end;
exit(false);
end;
local procedure JobJnlLineStartDate(JobJnlLine: Record "Job Journal Line"; var DateCaption: Text[30]): Date
begin
DateCaption := JobJnlLine.FieldCaption("Posting Date");
exit(JobJnlLine."Posting Date");
end;
local procedure FindJobResPrice(var JobResPrice: Record "Job Resource Price"; WorkTypeCode: Code[10]): Boolean
begin
JobResPrice.SetRange("Work Type Code", WorkTypeCode);
if JobResPrice.FindFirst() then
exit(true);
JobResPrice.SetRange("Work Type Code", '');
exit(JobResPrice.FindFirst())
end;
/// <summary>
/// Finds and applies the resource price for a resource journal line.
/// </summary>
/// <param name="ResJournalLine">Specifies the resource journal line to find and apply the price for.</param>
procedure FindResPrice(var ResJournalLine: Record "Res. Journal Line")
begin
GLSetup.Get();
ResPrice.Init();
ResPrice.Code := ResJournalLine."Resource No.";
ResPrice."Work Type Code" := ResJournalLine."Work Type Code";
ResJournalLine.BeforeFindResPrice(ResPrice);
CODEUNIT.Run(CODEUNIT::"Resource-Find Price", ResPrice);
ResJournalLine.AfterFindResPrice(ResPrice);
ResJournalLine."Unit Price" :=
Round(ResPrice."Unit Price" * ResJournalLine."Qty. per Unit of Measure", GLSetup."Unit-Amount Rounding Precision");
ResJournalLine.Validate("Unit Price");
end;
#if not CLEAN28
internal procedure RunOnAfterCalcBestUnitPrice(var SalesPrice: Record "Sales Price"; var BestSalesPrice: Record "Sales Price")
begin
OnAfterCalcBestUnitPrice(SalesPrice, BestSalesPrice, false);
end;
#endif
[IntegrationEvent(false, false)]
local procedure OnAfterCalcBestUnitPrice(var SalesPrice: Record "Sales Price"; var BestSalesPrice: Record "Sales Price"; FoundSalesPrice: Boolean)
begin
end;
#if not CLEAN28
internal procedure RunOnAfterCalcBestUnitPriceAsItemUnitPrice(var SalesPrice: Record "Sales Price"; var Item2: Record Item)
begin
OnAfterCalcBestUnitPriceAsItemUnitPrice(SalesPrice, Item2);
end;
#endif
[IntegrationEvent(false, false)]
local procedure OnAfterCalcBestUnitPriceAsItemUnitPrice(var SalesPrice: Record "Sales Price"; var Item: Record Item)
begin
end;
#if not CLEAN28
internal procedure RunOnAfterCalcLineAmount(SalesPrice: Record "Sales Price"; var LineAmount: Decimal; var LineDiscPerCent: Decimal)
begin
OnAfterCalcLineAmount(SalesPrice, LineAmount, LineDiscPerCent);
end;
#endif
[IntegrationEvent(false, false)]
local procedure OnAfterCalcLineAmount(SalesPrice: Record "Sales Price"; var LineAmount: Decimal; var LineDiscPerCent: Decimal)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterCopyJobResPriceToJobJnlLine(var JobJnlLine: Record "Job Journal Line")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterFindItemJnlLinePrice(var ItemJournalLine: Record "Item Journal Line"; var SalesPrice: Record "Sales Price"; CalledByFieldNo: Integer; FoundSalesPrice: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterFindJobJnlLineResPrice(var JobJournalLine: Record "Job Journal Line"; var ResourcePrice: Record "Resource Price"; CalledByFieldNo: Integer; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterFindJobJnlLineLineDisc(var JobJournalLine: Record "Job Journal Line"; var TempSalesLineDisc: Record "Sales Line Discount" temporary)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterFindJobPlanningLineLineDisc(var JobPlanningLine: Record "Job Planning Line"; var TempSalesLineDisc: Record "Sales Line Discount" temporary)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterFindJobPlanningLineResPrice(var JobPlanningLine: Record "Job Planning Line"; var ResourcePrice: Record "Resource Price"; CalledByFieldNo: Integer; var AllowLineDisc: Boolean; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterFindStdItemJnlLinePrice(var StdItemJnlLine: Record "Standard Item Journal Line"; var SalesPrice: Record "Sales Price"; CalledByFieldNo: Integer)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterFindSalesLinePrice(var SalesLine: Record "Sales Line"; var SalesHeader: Record "Sales Header"; var SalesPrice: Record "Sales Price"; var ResourcePrice: Record "Resource Price"; CalledByFieldNo: Integer; var FoundSalesPrice: Boolean; Qty: Decimal; QtyPerUOM: Decimal; LineDiscPerCent: Decimal; AllowLineDisc: Boolean; AllowInvDisc: Boolean; PricesInCurrency: Boolean; VATBusPostingGr: Code[20]; VATCalcType: Option "Normal VAT","Reverse Charge VAT","Full VAT","Sales Tax"; VATPerCent: Decimal; CurrencyFactor: Decimal)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterFindSalesLineLineDisc(var SalesLine: Record "Sales Line"; var SalesHeader: Record "Sales Header"; var SalesLineDiscount: Record "Sales Line Discount")
begin
end;
#if not CLEAN28
internal procedure RunOnAfterFindSalesPrice(var ToSalesPrice: Record "Sales Price"; var FromSalesPrice: Record "Sales Price"; QtyPerUOM: Decimal; Qty: Decimal; CustNo: Code[20]; ContNo: Code[20]; CustPriceGrCode: Code[10]; CampaignNo: Code[20]; ItemNo: Code[20]; VariantCode: Code[10]; UOM: Code[10]; CurrencyCode: Code[10]; StartingDate: Date; ShowAll: Boolean)
begin
OnAfterFindSalesPrice(ToSalesPrice, FromSalesPrice, QtyPerUOM, Qty, CustNo, ContNo, CustPriceGrCode, CampaignNo, ItemNo, VariantCode, UOM, CurrencyCode, StartingDate, ShowAll);
end;
#endif
[IntegrationEvent(false, false)]
local procedure OnAfterFindSalesPrice(var ToSalesPrice: Record "Sales Price"; var FromSalesPrice: Record "Sales Price"; QtyPerUOM: Decimal; Qty: Decimal; CustNo: Code[20]; ContNo: Code[20]; CustPriceGrCode: Code[10]; CampaignNo: Code[20]; ItemNo: Code[20]; VariantCode: Code[10]; UOM: Code[10]; CurrencyCode: Code[10]; StartingDate: Date; ShowAll: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterFindSalesLineItemPrice(var SalesLine: Record "Sales Line"; var TempSalesPrice: Record "Sales Price" temporary; var FoundSalesPrice: Boolean; CalledByFieldNo: Integer)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterFindSalesLineResPrice(var SalesLine: Record "Sales Line"; var ResPrice: Record "Resource Price"; CalledByFieldNo: Integer)
begin
end;
#if not CLEAN28
internal procedure RunOnAfterFindSalesLineDisc(var ToSalesLineDisc: Record "Sales Line Discount"; CustNo: Code[20]; ContNo: Code[20]; CustDiscGrCode: Code[20]; CampaignNo: Code[20]; ItemNo: Code[20]; ItemDiscGrCode: Code[20]; VariantCode: Code[10]; UOM: Code[10]; CurrencyCode: Code[10]; StartingDate: Date; ShowAll: Boolean)
begin
OnAfterFindSalesLineDisc(ToSalesLineDisc, CustNo, ContNo, CustDiscGrCode, CampaignNo, ItemNo, ItemDiscGrCode, VariantCode, UOM, CurrencyCode, StartingDate, ShowAll);
end;
#endif
[IntegrationEvent(false, false)]
local procedure OnAfterFindSalesLineDisc(var ToSalesLineDisc: Record "Sales Line Discount"; CustNo: Code[20]; ContNo: Code[20]; CustDiscGrCode: Code[20]; CampaignNo: Code[20]; ItemNo: Code[20]; ItemDiscGrCode: Code[20]; VariantCode: Code[10]; UOM: Code[10]; CurrencyCode: Code[10]; StartingDate: Date; ShowAll: Boolean)
begin
end;
#if not CLEAN28
internal procedure RunOnAfterFindServLinePrice(var ServiceLine: Record Microsoft.Service.Document."Service Line"; var ServiceHeader: Record Microsoft.Service.Document."Service Header"; var SalesPrice: Record "Sales Price"; var ResourcePrice: Record "Resource Price"; var ServiceCost: Record Microsoft.Service.Pricing."Service Cost"; CalledByFieldNo: Integer)
begin
OnAfterFindServLinePrice(ServiceLine, ServiceHeader, SalesPrice, ResourcePrice, ServiceCost, CalledByFieldNo);
end;
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
[IntegrationEvent(false, false)]
local procedure OnAfterFindServLinePrice(var ServiceLine: Record Microsoft.Service.Document."Service Line"; var ServiceHeader: Record Microsoft.Service.Document."Service Header"; var SalesPrice: Record "Sales Price"; var ResourcePrice: Record "Resource Price"; var ServiceCost: Record Microsoft.Service.Pricing."Service Cost"; CalledByFieldNo: Integer)
begin
end;
#endif
#if not CLEAN28
internal procedure RunOnAfterFindServLineResPrice(var ServiceLine: Record Microsoft.Service.Document."Service Line"; var ResPrice: Record "Resource Price"; var HideResUnitPriceMessage: Boolean; CalledByFieldNo: Integer; var IsHandled: Boolean)
begin
OnAfterFindServLineResPrice(ServiceLine, ResPrice, HideResUnitPriceMessage, CalledByFieldNo, IsHandled);
end;
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
[IntegrationEvent(false, false)]
local procedure OnAfterFindServLineResPrice(var ServiceLine: Record Microsoft.Service.Document."Service Line"; var ResPrice: Record "Resource Price"; var HideResUnitPriceMessage: Boolean; CalledByFieldNo: Integer; var IsHandled: Boolean)
begin
end;
#endif
#if not CLEAN28
internal procedure RunOnAfterFindServLineDisc(var ServiceLine: Record Microsoft.Service.Document."Service Line"; var ServiceHeader: Record Microsoft.Service.Document."Service Header"; var SalesLineDiscount: Record "Sales Line Discount")
begin
OnAfterFindServLineDisc(ServiceLine, ServiceHeader, SalesLineDiscount);
end;
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
[IntegrationEvent(false, false)]
local procedure OnAfterFindServLineDisc(var ServiceLine: Record Microsoft.Service.Document."Service Line"; var ServiceHeader: Record Microsoft.Service.Document."Service Header"; var SalesLineDiscount: Record "Sales Line Discount")
begin
end;
#endif
[IntegrationEvent(false, false)]
local procedure OnAfterGetSalesLinePrice(var SalesHeader: Record "Sales Header"; var SalesLine: Record "Sales Line"; var TempSalesPrice: Record "Sales Price" temporary)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterGetSalesLineLineDisc(var SalesLine: Record "Sales Line"; var SalesLineDiscount: Record "Sales Line Discount")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterJobJnlLineFindJTPriceGLAccount(var JobJournalLine: Record "Job Journal Line")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterJobJnlLineFindJTPriceItem(var JobJournalLine: Record "Job Journal Line")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterJobJnlLineFindJTPriceResource(var JobJournalLine: Record "Job Journal Line")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterJobJnlLineLineDiscExists(var JobJournalLine: Record "Job Journal Line")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterJobPlanningLineLineDiscExists(var JobPlanningLine: Record "Job Planning Line")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterSalesLineLineDiscExists(var SalesLine: Record "Sales Line"; var SalesHeader: Record "Sales Header"; var TempSalesLineDisc: Record "Sales Line Discount" temporary; ShowAll: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterSalesLinePriceExists(var SalesLine: Record "Sales Line"; var SalesHeader: Record "Sales Header"; var TempSalesPrice: Record "Sales Price" temporary; ShowAll: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterSalesLinePriceExistsProcedure(var SalesHeader: Record "Sales Header"; var SalesLine: Record "Sales Line"; Res: Record Resource; var DateCaption: Text[30]; var ShowAll: Boolean; var Result: Boolean)
begin
end;
#if not CLEAN28
internal procedure RunOnAfterServLinePriceExists(var ServiceLine: Record Microsoft.Service.Document."Service Line")
begin
OnAfterServLinePriceExists(ServiceLine);
end;
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
[IntegrationEvent(false, false)]
local procedure OnAfterServLinePriceExists(var ServiceLine: Record Microsoft.Service.Document."Service Line")
begin
end;
#endif
#if not CLEAN28
internal procedure RunOnAfterServLineLineDiscExists(var ServiceLine: Record Microsoft.Service.Document."Service Line")
begin
OnAfterServLineLineDiscExists(ServiceLine);
end;
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
[IntegrationEvent(false, false)]
local procedure OnAfterServLineLineDiscExists(var ServiceLine: Record Microsoft.Service.Document."Service Line")
begin
end;
#endif
[IntegrationEvent(false, false)]
local procedure OnBeforeActivatedCampaignExists(var ToCampaignTargetGr: Record "Campaign Target Group"; CustNo: Code[20]; ContNo: Code[20]; CampaignNo: Code[20]; var IsHandled: Boolean);
begin
end;
#if not CLEAN28
internal procedure RunOnBeforeCalcBestLineDisc(var SalesLineDisc: Record "Sales Line Discount"; Item2: Record Item; var IsHandled: Boolean; QtyPerUOM2: Decimal; Qty2: Decimal);
begin
OnBeforeCalcBestLineDisc(SalesLineDisc, Item2, IsHandled, QtyPerUOM2, Qty2);
end;
#endif
[IntegrationEvent(false, false)]
local procedure OnBeforeCalcBestLineDisc(var SalesLineDisc: Record "Sales Line Discount"; Item: Record Item; var IsHandled: Boolean; QtyPerUOM: Decimal; Qty: Decimal);
begin
end;
#if not CLEAN28
internal procedure RunOnBeforeCalcBestUnitPrice(var SalesPrice: Record "Sales Price"; var IsHandled: Boolean)
begin
OnBeforeCalcBestUnitPrice(SalesPrice, IsHandled);
end;
#endif
[IntegrationEvent(false, false)]
local procedure OnBeforeCalcBestUnitPrice(var SalesPrice: Record "Sales Price"; var IsHandled: Boolean)
begin
end;
#if not CLEAN28
internal procedure RunOnBeforeConvertPriceToVAT(var VATPostingSetup: Record "VAT Posting Setup"; var UnitPrice: Decimal; var IsHandled: Boolean)
begin
OnBeforeConvertPriceToVAT(VATPostingSetup, UnitPrice, IsHandled);
end;
#endif
[IntegrationEvent(false, false)]
local procedure OnBeforeConvertPriceToVAT(var VATPostingSetup: Record "VAT Posting Setup"; var UnitPrice: Decimal; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeCopyJobItemPriceToJobJnlLine(var JobJnlLine: Record "Job Journal Line"; JobItemPrice: Record "Job Item Price"; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeCopyJobItemPriceToJobPlanLine(var JobPlanningLine: Record "Job Planning Line"; JobItemPrice: Record "Job Item Price"; var IsHandled: Boolean)
begin
end;
#if not CLEAN28
internal procedure RunOnBeforeCopySalesPriceToSalesPrice(var FromSalesPrice: Record "Sales Price"; var ToSalesPrice: Record "Sales Price"; var IsHandled: Boolean)
begin
OnBeforeCopySalesPriceToSalesPrice(FromSalesPrice, ToSalesPrice, IsHandled);
end;
#endif
[IntegrationEvent(false, false)]
local procedure OnBeforeCopySalesPriceToSalesPrice(var FromSalesPrice: Record "Sales Price"; var ToSalesPrice: Record "Sales Price"; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeCopySalesLineDiscToSalesLineDisc(var FromSalesLineDiscount: Record "Sales Line Discount"; var ToSalesLineDiscount: Record "Sales Line Discount"; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeFindAnalysisReportPrice(ItemNo: Code[20]; Date: Date; var UnitPrice: Decimal; var IsHandled: Boolean; var FoundSalesPrice: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeFindItemJnlLinePrice(var ItemJournalLine: Record "Item Journal Line"; CalledByFieldNo: Integer; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeFindJobJnlLinePrice(var JobJournalLine: Record "Job Journal Line"; CalledByFieldNo: Integer; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeFindJobPlanningLinePrice(var JobPlanningLine: Record "Job Planning Line"; CalledByFieldNo: Integer; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeFindJobJnlLineResPrice(var JobJournalLine: Record "Job Journal Line"; var ResourcePrice: Record "Resource Price")
begin
end;
#if not CLEAN28
internal procedure RunOnBeforeFindSalesPrice(var ToSalesPrice: Record "Sales Price"; var FromSalesPrice: Record "Sales Price"; var QtyPerUOM: Decimal; var Qty: Decimal; var CustNo: Code[20]; var ContNo: Code[20]; var CustPriceGrCode: Code[10]; var CampaignNo: Code[20]; var ItemNo: Code[20]; var VariantCode: Code[10]; var UOM: Code[10]; var CurrencyCode: Code[10]; var StartingDate: Date; var ShowAll: Boolean)
begin
OnBeforeFindSalesPrice(ToSalesPrice, FromSalesPrice, QtyPerUOM, Qty, CustNo, ContNo, CustPriceGrCode, CampaignNo, ItemNo, VariantCode, UOM, CurrencyCode, StartingDate, ShowAll);
end;
#endif
[IntegrationEvent(false, false)]
local procedure OnBeforeFindSalesPrice(var ToSalesPrice: Record "Sales Price"; var FromSalesPrice: Record "Sales Price"; var QtyPerUOM: Decimal; var Qty: Decimal; var CustNo: Code[20]; var ContNo: Code[20]; var CustPriceGrCode: Code[10]; var CampaignNo: Code[20]; var ItemNo: Code[20]; var VariantCode: Code[10]; var UOM: Code[10]; var CurrencyCode: Code[10]; var StartingDate: Date; var ShowAll: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeFindSalesLinePrice(var SalesLine: Record "Sales Line"; SalesHeader: Record "Sales Header"; CalledByFieldNo: Integer; var IsHandled: Boolean)
begin
end;
#if not CLEAN28
internal procedure RunOnBeforeFindSalesLineDisc(var ToSalesLineDisc: Record "Sales Line Discount"; var CustNo: Code[20]; ContNo: Code[20]; var CustDiscGrCode: Code[20]; var CampaignNo: Code[20]; var ItemNo: Code[20]; var ItemDiscGrCode: Code[20]; var VariantCode: Code[10]; var UOM: Code[10]; var CurrencyCode: Code[10]; var StartingDate: Date; var ShowAll: Boolean)
begin
OnBeforeFindSalesLineDisc(ToSalesLineDisc, CustNo, ContNo, CustDiscGrCode, CampaignNo, ItemNo, ItemDiscGrCode, VariantCode, UOM, CurrencyCode, StartingDate, ShowAll);
end;
#endif
[IntegrationEvent(false, false)]
local procedure OnBeforeFindSalesLineDisc(var ToSalesLineDisc: Record "Sales Line Discount"; var CustNo: Code[20]; ContNo: Code[20]; var CustDiscGrCode: Code[20]; var CampaignNo: Code[20]; var ItemNo: Code[20]; var ItemDiscGrCode: Code[20]; var VariantCode: Code[10]; var UOM: Code[10]; var CurrencyCode: Code[10]; var StartingDate: Date; var ShowAll: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeFindSalesLineLineDisc(var SalesLine: Record "Sales Line"; var SalesHeader: Record "Sales Header"; var IsHandled: Boolean)
begin
end;
#if not CLEAN28
internal procedure RunOnBeforeFindServLinePrice(var ServiceLine: Record Microsoft.Service.Document."Service Line"; ServiceHeader: Record Microsoft.Service.Document."Service Header"; CalledByFieldNo: Integer; var IsHandled: Boolean)
begin
OnBeforeFindServLinePrice(ServiceLine, ServiceHeader, CalledByFieldNo, IsHandled);
end;
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
[IntegrationEvent(false, false)]
local procedure OnBeforeFindServLinePrice(var ServiceLine: Record Microsoft.Service.Document."Service Line"; ServiceHeader: Record Microsoft.Service.Document."Service Header"; CalledByFieldNo: Integer; var IsHandled: Boolean)
begin
end;
#endif
#if not CLEAN28
internal procedure RunOnBeforeFindServLineDisc(var ServiceHeader: Record Microsoft.Service.Document."Service Header"; var ServiceLine: Record Microsoft.Service.Document."Service Line"; var IsHandled: Boolean)
begin
OnBeforeFindServLineDisc(ServiceHeader, ServiceLine, IsHandled);
end;
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
[IntegrationEvent(false, false)]
local procedure OnBeforeFindServLineDisc(var ServiceHeader: Record Microsoft.Service.Document."Service Header"; var ServiceLine: Record Microsoft.Service.Document."Service Line"; var IsHandled: Boolean)
begin
end;
#endif
[IntegrationEvent(false, false)]
local procedure OnBeforeFindStdItemJnlLinePrice(var StandardItemJournalLine: Record "Standard Item Journal Line"; CalledByFieldNo: Integer; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeGetSalesLinePrice(var SalesHeader: Record "Sales Header"; var SalesLine: Record "Sales Line"; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeGetSalesLineLineDisc(var SalesHeader: Record "Sales Header"; var SalesLine: Record "Sales Line"; var IsHandled: Boolean)
begin
end;
#if not CLEAN28
internal procedure RunOnBeforeGetServLinePrice(ServHeader: Record Microsoft.Service.Document."Service Header"; var ServLine: Record Microsoft.Service.Document."Service Line"; var IsHandled: Boolean)
begin
OnBeforeGetServLinePrice(ServHeader, ServLine, IsHandled);
end;
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
[IntegrationEvent(false, false)]
local procedure OnBeforeGetServLinePrice(ServHeader: Record Microsoft.Service.Document."Service Header"; var ServLine: Record Microsoft.Service.Document."Service Line"; var IsHandled: Boolean)
begin
end;
#endif
#if not CLEAN28
internal procedure RunOnBeforeGetServLineDisc(var ServiceHeader: Record Microsoft.Service.Document."Service Header"; var ServiceLine: Record Microsoft.Service.Document."Service Line"; var IsHandled: Boolean)
begin
OnBeforeGetServLineDisc(ServiceHeader, ServiceLine, IsHandled);
end;
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
[IntegrationEvent(false, false)]
local procedure OnBeforeGetServLineDisc(var ServiceHeader: Record Microsoft.Service.Document."Service Header"; var ServiceLine: Record Microsoft.Service.Document."Service Line"; var IsHandled: Boolean)
begin
end;
#endif
[IntegrationEvent(false, false)]
local procedure OnBeforeJobJnlLineLineDiscExists(var JobJournalLine: Record "Job Journal Line")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeJobPlanningLineLineDiscExists(var JobPlanningLine: Record "Job Planning Line")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeJobPlanningLineFindJTPrice(var JobPlanningLine: Record "Job Planning Line"; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeSalesHeaderStartDate(var SalesHeader: Record "Sales Header"; var DateCaption: Text[30]; var StartDate: Date; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeNoOfSalesLineLineDisc(var SalesHeader: Record "Sales Header"; var SalesLine: Record "Sales Line"; ShowAll: Boolean; var Result: Integer; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeNoOfSalesLinePrice(var SalesHeader: Record "Sales Header"; var SalesLine: Record "Sales Line"; ShowAll: Boolean; var Result: Integer; var IsHandled: Boolean)
begin
end;
#if not CLEAN28
internal procedure RunOnBeforeNoOfServLineLineDisc(var ServiceHeader: Record Microsoft.Service.Document."Service Header"; var ServiceLine: Record Microsoft.Service.Document."Service Line"; ShowAll: Boolean; var Result: Integer; var IsHandled: Boolean)
begin
OnBeforeNoOfServLineLineDisc(ServiceHeader, ServiceLine, ShowAll, Result, IsHandled);
end;
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
[IntegrationEvent(false, false)]
local procedure OnBeforeNoOfServLineLineDisc(var ServiceHeader: Record Microsoft.Service.Document."Service Header"; var ServiceLine: Record Microsoft.Service.Document."Service Line"; ShowAll: Boolean; var Result: Integer; var IsHandled: Boolean)
begin
end;
#endif
#if not CLEAN28
internal procedure RunOnBeforeNoOfServLinePrice(var ServiceHeader: Record Microsoft.Service.Document."Service Header"; var ServiceLine: Record Microsoft.Service.Document."Service Line"; ShowAll: Boolean; var Result: Integer; var IsHandled: Boolean)
begin
OnBeforeNoOfServLinePrice(ServiceHeader, ServiceLine, ShowAll, Result, IsHandled);
end;
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
[IntegrationEvent(false, false)]
local procedure OnBeforeNoOfServLinePrice(var ServiceHeader: Record Microsoft.Service.Document."Service Header"; var ServiceLine: Record Microsoft.Service.Document."Service Line"; ShowAll: Boolean; var Result: Integer; var IsHandled: Boolean)
begin
end;
#endif
[IntegrationEvent(false, false)]
local procedure OnBeforeSalesLineLineDiscExists(var SalesLine: Record "Sales Line"; var SalesHeader: Record "Sales Header"; var TempSalesLineDisc: Record "Sales Line Discount" temporary; StartingDate: Date; Qty: Decimal; QtyPerUOM: Decimal; ShowAll: Boolean; var IsHandled: Boolean; Sender: Codeunit "Sales Price Calc. Mgt.")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeSalesLinePriceExists(var SalesLine: Record "Sales Line"; var SalesHeader: Record "Sales Header"; var TempSalesPrice: Record "Sales Price" temporary; Currency: Record Currency; CurrencyFactor: Decimal; StartingDate: Date; Qty: Decimal; QtyPerUOM: Decimal; ShowAll: Boolean; var InHandled: Boolean; Sender: Codeunit "Sales Price Calc. Mgt.")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeSalesLinePriceExistsProcedure(var SalesHeader: Record "Sales Header"; var SalesLine: Record "Sales Line"; ShowAll: Boolean; var TempSalesPrice: Record "Sales Price" temporary; var Result: Boolean; var IsHandled: Boolean)
begin
end;
#if not CLEAN28
internal procedure RunOnBeforeServLinePriceExists(var ServiceLine: Record Microsoft.Service.Document."Service Line"; var ServiceHeader: Record Microsoft.Service.Document."Service Header"; var TempSalesPrice: Record "Sales Price" temporary; ShowAll: Boolean; var IsHandled: Boolean)
begin
OnBeforeServLinePriceExists(ServiceLine, ServiceHeader, TempSalesPrice, ShowAll, IsHandled);
end;
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
[IntegrationEvent(false, false)]
local procedure OnBeforeServLinePriceExists(var ServiceLine: Record Microsoft.Service.Document."Service Line"; var ServiceHeader: Record Microsoft.Service.Document."Service Header"; var TempSalesPrice: Record "Sales Price" temporary; ShowAll: Boolean; var IsHandled: Boolean)
begin
end;
#endif
#if not CLEAN28
internal procedure RunOnBeforeServLineLineDiscExists(var ServiceLine: Record Microsoft.Service.Document."Service Line"; var ServiceHeader: Record Microsoft.Service.Document."Service Header"; var TempSalesLineDisc: Record "Sales Line Discount" temporary; ShowAll: Boolean; var IsHandled: Boolean)
begin
OnBeforeServLineLineDiscExists(ServiceLine, ServiceHeader, TempSalesLineDisc, ShowAll, IsHandled);
end;
[Obsolete('Moved to codeunit ServPriceCalcMgt', '28.0')]
[IntegrationEvent(false, false)]
local procedure OnBeforeServLineLineDiscExists(var ServiceLine: Record Microsoft.Service.Document."Service Line"; var ServiceHeader: Record Microsoft.Service.Document."Service Header"; var TempSalesLineDisc: Record "Sales Line Discount" temporary; ShowAll: Boolean; var IsHandled: Boolean)
begin
end;
#endif
[IntegrationEvent(false, false)]
local procedure OnGetCustNoForSalesHeader(var SalesHeader: Record "Sales Header"; var CustomerNo: Code[20])
begin
end;
[IntegrationEvent(false, false)]
local procedure OnFindJobJnlLinePriceOnBeforeJobJnlLineFindJTPrice(var JobJnlLine: Record "Job Journal Line")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnFindJobJnlLinePriceOnBeforeResourceGetJob(var JobJnlLine: Record "Job Journal Line"; var IsHandled: Boolean)
begin
end;
#if not CLEAN28
internal procedure RunOnFindSalesLineDiscOnAfterSetFilters(var SalesLineDiscount: Record "Sales Line Discount")
begin
OnFindSalesLineDiscOnAfterSetFilters(SalesLineDiscount);
end;
#endif
[IntegrationEvent(false, false)]
local procedure OnFindSalesLineDiscOnAfterSetFilters(var SalesLineDiscount: Record "Sales Line Discount")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnFindSalesLineDiscOnAfterCopyItemDiscGroup(var FromSalesLineDiscount: Record "Sales Line Discount"; var ToSalesLineDiscount: Record "Sales Line Discount")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnFindSalesLineLineDiscOnBeforeCalcLineDisc(var SalesHeader: Record "Sales Header"; SalesLine: Record "Sales Line"; var TempSalesLineDiscount: Record "Sales Line Discount" temporary; var Qty: Decimal; var QtyPerUOM: Decimal; var IsHandled: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnJobJnlLineFindJTPriceOnAfterSetJobItemPriceFilters(var JobItemPrice: Record "Job Item Price"; JobJnlLine: Record "Job Journal Line");
begin
end;
[IntegrationEvent(false, false)]
local procedure OnJobPlanningLineFindJTPriceOnAfterSetJobGLAccPriceFilters(var JobItemPrice: Record "Job G/L Account Price"; JobPlanningLine: Record "Job Planning Line")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnJobPlanningLineFindJTPriceOnAfterSetJobItemPriceFilters(var JobItemPrice: Record "Job Item Price"; JobPlanningLine: Record "Job Planning Line")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnJobPlanningLineFindJTPriceOnAfterSetJobResPriceFilters(var JobResPrice: Record "Job Resource Price"; JobPlanningLine: Record "Job Planning Line")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnFindJobPlanningLinePriceOnBeforeJobPlanningLineFindJTPrice(var JobPlanningLine: Record "Job Planning Line"; var ResPrice: Record "Resource Price")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnFindSalesLinePriceOnAfterSetResPrice(var SalesLine: Record "Sales Line"; var ResPrice: Record "Resource Price")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnFindSalesLinePriceOnAfterSetLineDisc(var SalesLine: Record "Sales Line"; var Qty: Decimal; var QtyPerUOM: Decimal)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnFindSalesLinePriceOnItemTypeOnAfterSetUnitPrice(var SalesHeader: Record "Sales Header"; var SalesLine: Record "Sales Line"; var TempSalesPrice: Record "Sales Price" temporary; CalledByFieldNo: Integer; FoundSalesPrice: Boolean)
begin
end;
#if not CLEAN28
internal procedure RunOnBeforeCalcBestUnitPriceConvertPrice(var SalesPrice: Record "Sales Price"; var IsHandled: Boolean; Item: Record "Item")
begin
OnBeforeCalcBestUnitPriceConvertPrice(SalesPrice, IsHandled, Item);
end;
#endif
[IntegrationEvent(true, false)]
local procedure OnBeforeCalcBestUnitPriceConvertPrice(var SalesPrice: Record "Sales Price"; var IsHandled: Boolean; Item: Record "Item")
begin
end;
#if not CLEAN28
internal procedure RunOnCalcBestUnitPriceOnBeforeCalcBestUnitPriceConvertPrice(var SalesPrice: Record "Sales Price"; Qty: Decimal; var IsHandled: Boolean; var Item: Record Item)
var
DummyBestSalesPriceFound: Boolean;
begin
OnCalcBestUnitPriceOnBeforeCalcBestUnitPriceConvertPrice(
SalesPrice, Qty, IsHandled, Item, 0, SalesPrice, DummyBestSalesPriceFound,
VATCalcType, PricesInclVAT, VATPerCent, PricesInCurrency, ExchRateDate, CurrencyFactor,
Currency, LineDiscPerCent, VATBusPostingGr);
end;
#endif
[IntegrationEvent(false, false)]
local procedure OnCalcBestUnitPriceOnBeforeCalcBestUnitPriceConvertPrice(var SalesPrice: Record "Sales Price"; Qty: Decimal; var IsHandled: Boolean; var Item: Record Item; QtyPerUOM: Decimal; var BestSalesPrice: Record "Sales Price"; var BestSalesPriceFound: Boolean; VATCalcType: Option; PricesInclVAT: Boolean; VATPerCent: Decimal; PricesInCurrency: Boolean; ExchRateDate: Date; CurrencyFactor: Decimal; Currency: Record Currency; LineDiscPerCent: Decimal; VATBusPostingGr: Code[20])
begin
end;
#if not CLEAN28
internal procedure RunOnSetResPriceOnAfterInit(var ResourcePrice: Record "Resource Price")
begin
OnSetResPriceOnAfterInit(ResourcePrice);
end;
#endif
[IntegrationEvent(false, false)]
local procedure OnSetResPriceOnAfterInit(var ResourcePrice: Record "Resource Price")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnFindSalesLinePriceOnCalcBestUnitPrice(SalesLine: Record "Sales Line"; var TempSalesPrice: Record "Sales Price" temporary)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeValidateLineDiscountOnSalesLine(var SalesLine: Record "Sales Line"; var SalesLineDiscount: Record "Sales Line Discount" temporary; var IsHandled: Boolean)
begin
end;
}