Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ codeunit 8062 "Billing Proposal"
PurchaseCreditMemoExistsForBillingLineQst: Label 'There is a purchase credit memo that needs to be posted before an invoice can be created. Do you want to open the credit memo?';
BillingLinesForAllContractLinesExistsErr: Label 'There are billing lines for all contract lines. For contract lines with billing lines, the invoice must be created in recurring billing.';
NotAuthorizedToClearOrDeleteDocumentErr: Label 'You are not authorized to clear billing templates or delete billing documents. To perform these actions, you must be set up as an Auto Contract Billing user in the User Setup.';
BillingProposalProgressTxt: Label 'Creating Billing Proposal...\Contract No. #1#################################\Partner No. #2#################################\Processed: #3########## / #4##########', Comment = '%1=Contract No., %2=Partner No., %3=Contracts processed, %4=Total contracts';

procedure InitTempTable(var TempBillingLine: Record "Billing Line" temporary; GroupBy: Enum "Contract Billing Grouping")
var
Expand Down Expand Up @@ -154,8 +155,11 @@ codeunit 8062 "Billing Proposal"
BillingTemplate: Record "Billing Template";
CustomerContract: Record "Customer Subscription Contract";
VendorContract: Record "Vendor Subscription Contract";
ProposalWindow: Dialog;
FilterText: Text;
BillingRhythmFilterText: Text;
TotalContractsCount: Integer;
ContractCounter: Integer;
begin
SalesHeaderGlobal.Reset();
BillingTemplate.Get(BillingTemplateCode);
Expand All @@ -175,20 +179,46 @@ codeunit 8062 "Billing Proposal"
if FilterText <> '' then
CustomerContract.SetView(FilterText);
BillingRhythmFilterText := CustomerContract.GetFilter("Billing Rhythm Filter");
if GuiAllowed then begin
TotalContractsCount := CustomerContract.Count();
ProposalWindow.Open(BillingProposalProgressTxt);
ProposalWindow.Update(4, TotalContractsCount);
end;
if CustomerContract.FindSet() then
repeat
ContractCounter += 1;
if GuiAllowed then begin
ProposalWindow.Update(1, CustomerContract."No.");
ProposalWindow.Update(2, CustomerContract."Sell-to Customer No.");
ProposalWindow.Update(3, ContractCounter);
end;
ProcessContractServiceCommitments(BillingTemplate, CustomerContract."No.", '', BillingDate, BillingToDate, BillingRhythmFilterText, AutomatedBilling);
until CustomerContract.Next() = 0;
if GuiAllowed then
ProposalWindow.Close();
end;
"Service Partner"::Vendor:
begin
if FilterText <> '' then
VendorContract.SetView(FilterText);
BillingRhythmFilterText := VendorContract.GetFilter("Billing Rhythm Filter");
if GuiAllowed then begin
TotalContractsCount := VendorContract.Count();
ProposalWindow.Open(BillingProposalProgressTxt);
ProposalWindow.Update(4, TotalContractsCount);
end;
if VendorContract.FindSet() then
repeat
ContractCounter += 1;
if GuiAllowed then begin
ProposalWindow.Update(1, VendorContract."No.");
ProposalWindow.Update(2, VendorContract."Pay-to Vendor No.");
ProposalWindow.Update(3, ContractCounter);
end;
ProcessContractServiceCommitments(BillingTemplate, VendorContract."No.", '', BillingDate, BillingToDate, BillingRhythmFilterText, AutomatedBilling);
until VendorContract.Next() = 0;
if GuiAllowed then
ProposalWindow.Close();
end;
end;

Expand All @@ -200,16 +230,20 @@ codeunit 8062 "Billing Proposal"
begin
SalesHeaderGlobal.MarkedOnly(true);
if SalesHeaderGlobal.Count <> 0 then begin
Page.Run(Page::"Sales Credit Memos", SalesHeaderGlobal);
Message(CreditMemoPreventsProposalCreationLbl);
if GuiAllowed then
Page.Run(Page::"Sales Credit Memos", SalesHeaderGlobal);
if GuiAllowed then
Message(CreditMemoPreventsProposalCreationLbl);
end;
end;
Enum::"Service Partner"::Vendor:
begin
PurchaseHeaderGlobal.MarkedOnly(true);
if PurchaseHeaderGlobal.Count <> 0 then begin
Page.Run(Page::"Purchase Credit Memos", PurchaseHeaderGlobal);
Message(CreditMemoPreventsProposalCreationLbl);
if GuiAllowed then
Page.Run(Page::"Purchase Credit Memos", PurchaseHeaderGlobal);
if GuiAllowed then
Message(CreditMemoPreventsProposalCreationLbl);
end;
end;
end;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,18 @@ codeunit 8060 "Create Billing Documents"
if not RequestPageSelectionConfirmed() then
exit;

Window.Open(ProgressTxt);
Window.Update();
if GuiAllowed then begin
Window.Open(ProgressTxt);
Window.Update();
end;
if AutomatedBilling then
BillingLine.SetRange("Billing Error Log Entry No.", 0)
else
BillingLine.ModifyAll("Billing Error Log Entry No.", 0);

ProcessBillingLines(BillingLine);
Window.Close();
if GuiAllowed then
Window.Close();
if PostDocuments then
PostCreatedDocuments();
if not HideProcessingFinishedMessage then
Expand Down Expand Up @@ -89,17 +92,24 @@ codeunit 8060 "Create Billing Documents"
repeat
if IsNewHeaderNeededPerContract(PreviousContractNo) then begin
TestPreviousDocumentTotalInvoiceAmount(true, DiscountLineExists, PreviousContractNo);
if PreviousContractNo <> '' then
Commit();
CustomerContract.Get(TempBillingLine."Subscription Contract No.");
CreateSalesHeaderFromContract(CustomerContract);
InsertContractDescriptionSalesLines(TempBillingLine);
PreviousContractNo := TempBillingLine."Subscription Contract No.";
ContractsProcessedCount += 1;
Window.Update(1, CustomerContract."Sell-to Customer No.");
Window.Update(2, PreviousContractNo);
if GuiAllowed then begin
Window.Update(1, CustomerContract."Sell-to Customer No.");
Window.Update(2, PreviousContractNo);
Window.Update(3, ContractsProcessedCount);
end;
end;
InsertSalesLineFromTempBillingLine();
until TempBillingLine.Next() = 0;
TestPreviousDocumentTotalInvoiceAmount(true, DiscountLineExists, PreviousContractNo);
if PreviousContractNo <> '' then
Commit();
end;

local procedure CreatePurchaseDocumentsPerContract()
Expand All @@ -117,17 +127,24 @@ codeunit 8060 "Create Billing Documents"
repeat
if IsNewHeaderNeededPerContract(PreviousContractNo) then begin
TestPreviousDocumentTotalInvoiceAmount(false, DiscountLineExists, PreviousContractNo);
if PreviousContractNo <> '' then
Commit();
VendorContract.Get(TempBillingLine."Subscription Contract No.");
CreatePurchaseHeaderFromContract(VendorContract);
InsertContractDescriptionPurchaseLines(TempBillingLine);
PreviousContractNo := TempBillingLine."Subscription Contract No.";
ContractsProcessedCount += 1;
Window.Update(1, VendorContract."Pay-to Vendor No.");
Window.Update(2, PreviousContractNo);
if GuiAllowed then begin
Window.Update(1, VendorContract."Pay-to Vendor No.");
Window.Update(2, PreviousContractNo);
Window.Update(3, ContractsProcessedCount);
end;
end;
InsertPurchaseLineFromTempBillingLine();
until TempBillingLine.Next() = 0;
TestPreviousDocumentTotalInvoiceAmount(false, DiscountLineExists, PreviousContractNo);
if PreviousContractNo <> '' then
Commit();
end;

local procedure CreateSalesDocumentsPerCustomer()
Expand All @@ -149,13 +166,16 @@ codeunit 8060 "Create Billing Documents"
repeat
if IsNewSalesHeaderNeeded(PreviousCustomerNo, LastDetailOverview, PreviousCurrencyCode, PreviousContractNo) then begin
TestPreviousDocumentTotalInvoiceAmount(true, DiscountLineExists, PreviousContractNo);
if PreviousCustomerNo <> '' then
Commit();
CreateSalesHeaderForCustomerNo(TempBillingLine."Partner No.");
SalesHeader."Sub. Contract Detail Overview" := TempBillingLine."Detail Overview";
SalesHeader.Modify(false);
PreviousCustomerNo := TempBillingLine."Partner No.";
LastDetailOverview := TempBillingLine."Detail Overview";
PreviousCurrencyCode := TempBillingLine."Currency Code";
Window.Update(1, PreviousCustomerNo);
if GuiAllowed then
Window.Update(1, PreviousCustomerNo);
FirstContractDescriptionLineInserted := false;
end;
if TempBillingLine."Subscription Contract No." <> PreviousContractNo then begin
Expand All @@ -168,11 +188,16 @@ codeunit 8060 "Create Billing Documents"
end;
PreviousContractNo := TempBillingLine."Subscription Contract No.";
ContractsProcessedCount += 1;
Window.Update(2, PreviousContractNo);
if GuiAllowed then begin
Window.Update(2, PreviousContractNo);
Window.Update(3, ContractsProcessedCount);
end;
end;
InsertSalesLineFromTempBillingLine();
until TempBillingLine.Next() = 0;
TestPreviousDocumentTotalInvoiceAmount(true, DiscountLineExists, PreviousContractNo);
if PreviousCustomerNo <> '' then
Commit();
end;

local procedure CreatePurchaseDocumentsPerVendor()
Expand All @@ -195,10 +220,13 @@ codeunit 8060 "Create Billing Documents"
(TempBillingLine."Currency Code" <> PreviousCurrencyCode)
then begin
TestPreviousDocumentTotalInvoiceAmount(false, DiscountLineExists, PreviousContractNo);
if PreviousVendorNo <> '' then
Commit();
CreatePurchaseHeaderForVendorNo(TempBillingLine."Partner No.");
PreviousVendorNo := TempBillingLine."Partner No.";
PreviousCurrencyCode := TempBillingLine."Currency Code";
Window.Update(1, PreviousVendorNo);
if GuiAllowed then
Window.Update(1, PreviousVendorNo);
FirstContractDescriptionLineInserted := false;
end;
if TempBillingLine."Subscription Contract No." <> PreviousContractNo then begin
Expand All @@ -211,11 +239,16 @@ codeunit 8060 "Create Billing Documents"
end;
PreviousContractNo := TempBillingLine."Subscription Contract No.";
ContractsProcessedCount += 1;
Window.Update(2, PreviousContractNo);
if GuiAllowed then begin
Window.Update(2, PreviousContractNo);
Window.Update(3, ContractsProcessedCount);
end;
end;
InsertPurchaseLineFromTempBillingLine();
until TempBillingLine.Next() = 0;
TestPreviousDocumentTotalInvoiceAmount(false, DiscountLineExists, PreviousContractNo);
if PreviousVendorNo <> '' then
Commit();
end;

local procedure InsertSalesLineFromTempBillingLine()
Expand Down Expand Up @@ -302,10 +335,10 @@ codeunit 8060 "Create Billing Documents"
UsageDataBilling.SetRange("Subscription Contract Line No.", CustomerContractLine."Line No.");
UsageDataBilling.SetRange("Document Type", Enum::"Usage Based Billing Doc. Type"::None);
UsageDataBilling.SetRange("Document No.", '');
BillingLineNo := GetBillingLineNo(BillingLine.GetBillingDocumentTypeFromSalesDocumentType(SalesLine."Document Type"),
"Service Partner"::Customer, SalesLine."Document No.", CustomerContractLine."Subscription Contract No.", CustomerContractLine."Line No.");
if UsageDataBilling.FindSet() then
repeat
BillingLineNo := GetBillingLineNo(BillingLine.GetBillingDocumentTypeFromSalesDocumentType(SalesLine."Document Type"),
"Service Partner"::Customer, SalesLine."Document No.", CustomerContractLine."Subscription Contract No.", CustomerContractLine."Line No.");
UsageDataBilling.SaveDocumentValues(UsageBasedDocTypeConv.ConvertSalesDocTypeToUsageBasedBillingDocType(SalesLine."Document Type"), SalesLine."Document No.",
SalesLine."Line No.", BillingLineNo);
until UsageDataBilling.Next() = 0;
Expand Down Expand Up @@ -411,10 +444,10 @@ codeunit 8060 "Create Billing Documents"
UsageDataBilling.SetRange("Subscription Contract Line No.", ServiceCommitment."Subscription Contract Line No.");
UsageDataBilling.SetRange("Document Type", Enum::"Usage Based Billing Doc. Type"::None);
UsageDataBilling.SetRange("Document No.", '');
BillingLineNo := GetBillingLineNo(BillingLine.GetBillingDocumentTypeFromPurchaseDocumentType(PurchaseLine."Document Type"),
"Service Partner"::Vendor, PurchaseLine."Document No.", ServiceCommitment."Subscription Contract No.", ServiceCommitment."Subscription Contract Line No.");
if UsageDataBilling.FindSet() then
repeat
BillingLineNo := GetBillingLineNo(BillingLine.GetBillingDocumentTypeFromPurchaseDocumentType(PurchaseLine."Document Type"),
"Service Partner"::Vendor, PurchaseLine."Document No.", ServiceCommitment."Subscription Contract No.", ServiceCommitment."Subscription Contract Line No.");
UsageDataBilling.SaveDocumentValues(UsageBasedDocTypeConv.ConvertPurchaseDocTypeToUsageBasedBillingDocType(PurchaseLine."Document Type"), PurchaseLine."Document No.",
PurchaseLine."Line No.", BillingLineNo);
until UsageDataBilling.Next() = 0;
Expand Down Expand Up @@ -726,13 +759,18 @@ codeunit 8060 "Create Billing Documents"
CurrencyCode: Code[20];
PartnerNo: Code[20];
LineNo: Integer;
CachedCustomerContractNo: Code[20];
CachedVendorContractNo: Code[20];
begin
if BillingLine.FindSet() then
repeat
case BillingLine.Partner of
BillingLine.Partner::Customer:
begin
CustomerContract.Get(BillingLine."Subscription Contract No.");
if BillingLine."Subscription Contract No." <> CachedCustomerContractNo then begin
CustomerContract.Get(BillingLine."Subscription Contract No.");
CachedCustomerContractNo := BillingLine."Subscription Contract No.";
end;
case CustomerRecurringBillingGrouping of
CustomerRecurringBillingGrouping::"Sell-to Customer No.":
PartnerNo := CustomerContract."Sell-to Customer No.";
Expand All @@ -743,7 +781,10 @@ codeunit 8060 "Create Billing Documents"
end;
BillingLine.Partner::Vendor:
begin
VendorContract.Get(BillingLine."Subscription Contract No.");
if BillingLine."Subscription Contract No." <> CachedVendorContractNo then begin
VendorContract.Get(BillingLine."Subscription Contract No.");
CachedVendorContractNo := BillingLine."Subscription Contract No.";
end;
case VendorRecurringBillingGrouping of
VendorRecurringBillingGrouping::"Pay-to Vendor No.":
PartnerNo := VendorContract."Pay-to Vendor No.";
Expand Down Expand Up @@ -1030,6 +1071,8 @@ codeunit 8060 "Create Billing Documents"

local procedure ProcessingFinishedMessage()
begin
if not GuiAllowed then
exit;
if DocumentsCreatedCount = 0 then
Message(NoDocumentsCreatedMsg)
else
Expand Down Expand Up @@ -1404,7 +1447,7 @@ codeunit 8060 "Create Billing Documents"
PostDocuments: Boolean;
HideProcessingFinishedMessage: Boolean;
Window: Dialog;
ProgressTxt: Label 'Creating documents...\Partner No. #1#################################\Contract No. #2#################################', Comment = '%1=Partner No., %2=Contract No.';
ProgressTxt: Label 'Creating documents...\Partner No. #1#################################\Contract No. #2#################################\Contracts processed: #3##########', Comment = '%1=Partner No., %2=Contract No., %3=Contracts processed';
OnlyOneServicePartnerErr: Label 'You can create documents only for one type of partner at a time (Customer or Vendor). Please check your filters.';
UpdateRequiredErr: Label 'At least one Subscription Line was changed after billing proposal was created. Please check the lines marked with "Update Required" field and update the billing proposal before the billing documents can be created.';
BillingPeriodDescriptionTxt: Label 'Billing period: %1 to %2', Comment = '%1=Recurring Billing from, %2=Recurring Billing to';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,9 @@ table 8061 "Billing Line"
key(SK6; "Billing Template Code", Partner)
{
}
key(SK7; "Subscription Contract No.", "Subscription Contract Line No.", "Document No.", "Document Type", Partner)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jeffreybulanadi

Adding new keys can be costly and may negatively impact performance. Based on the analysis, this key degrades performance for some operations, so I recommend removing it.

Image

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. The function GetBillingLineNo might be a bottleneck indeed which I already observed on the real project. Instead of adding the key I suggest removing the function GetBillingLineNo completely and passing the "Billing Line No." as a denormalized field. That would bring more benefit to the performance then the key.

{
}
}

trigger OnDelete()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,9 @@ table 8059 "Subscription Line"
{

}
key(Key4; "Subscription Contract No.", "Next Billing Date", Partner)
{
}
}

trigger OnInsert()
Expand Down
Loading
Loading