Skip to content

Conversation

samra-singhammer
Copy link

@samra-singhammer samra-singhammer commented Sep 24, 2025

Summary

Fix incorrect usage data handling in usage-based contracts. Deleting invoice or credit memo lines currently leaves stale or unlinked usage data entries. The solution ensures related usage data is reset or removed properly while keeping posted-linked records intact.

Work Item(s)

Fixes AB#4856

@samra-singhammer samra-singhammer requested a review from a team as a code owner September 24, 2025 07:10
@github-actions github-actions bot added the From Fork Pull request is coming from a fork label Sep 24, 2025
@samra-singhammer
Copy link
Author

@samra-singhammer please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.

@microsoft-github-policy-service agree [company="{your company}"]

Options:

  • (default - no company specified) I have sole ownership of intellectual property rights to my Submissions and I am not making Submissions in the course of work for my employer.
@microsoft-github-policy-service agree
  • (when company given) I am making Submissions in the course of work for my employer (or my employer has intellectual property rights in my Submissions by contract or applicable law). I have permission from my employer to make Submissions and enter into this Agreement on behalf of my employer. By signing below, the defined term “You” includes me and my employer.
@microsoft-github-policy-service agree company="Microsoft"

Contributor License Agreement

@microsoft-github-policy-service agree [company="Singhammer IT Consulting AG"]

@samra-singhammer
Copy link
Author

@samra-singhammer please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.

@microsoft-github-policy-service agree [company="{your company}"]

Options:

  • (default - no company specified) I have sole ownership of intellectual property rights to my Submissions and I am not making Submissions in the course of work for my employer.
@microsoft-github-policy-service agree
  • (when company given) I am making Submissions in the course of work for my employer (or my employer has intellectual property rights in my Submissions by contract or applicable law). I have permission from my employer to make Submissions and enter into this Agreement on behalf of my employer. By signing below, the defined term “You” includes me and my employer.
@microsoft-github-policy-service agree company="Microsoft"

Contributor License Agreement

@microsoft-github-policy-service agree

@github-actions github-actions bot added the Linked Issue is linked to a Azure Boards work item label Sep 24, 2025
@github-actions github-actions bot added this to the Version 28.0 milestone Sep 24, 2025
Copy link
Contributor

@miljance miljance left a comment

Choose a reason for hiding this comment

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

The test TestBillingLineInUsageDataNoWhenBillingProposalIsCreated is failing.

Comment on lines 457 to 461
if UsageDataBilling.FindSet() then
repeat
UsageDataBilling."Billing Line Entry No." := BillingLine."Entry No.";
UsageDataBilling.Modify(false);
until UsageDataBilling.Next() = 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

I would prefer to use ModifyAll() here instead of Looping.

Copy link
Author

Choose a reason for hiding this comment

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

Done

exit;
if Rec.IsTemporary then
exit;
PurchaseHeader.Get(Rec."Document Type", Rec."Document No.");
Copy link
Contributor

Choose a reason for hiding this comment

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

There is a built in function named FilterDocumentWithLine in Usage Data Billing table. Can we use this one instead? I would like to avoid unintentionally breaking whatever might have been programmed at any other BC client.

Copy link
Author

Choose a reason for hiding this comment

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

Done

exit;
if Rec.IsTemporary then
exit;
SalesHeader.Get(Rec."Document Type", Rec."Document No.");
Copy link
Contributor

Choose a reason for hiding this comment

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

For whatever reason there might be Sales Lines without existing Sales Header. I would thus prefer conditional Get.

Copy link
Author

Choose a reason for hiding this comment

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

Done

Comment on lines 453 to 456
UsageDataBilling.FilterOnServiceCommitment(SubscriptionLine);
UsageDataBilling.SetRange("Document Type", "Usage Based Billing Doc. Type"::None);
UsageDataBilling.SetFilter("Charge Start Date", '<=%1', BillingLine."Billing from");
UsageDataBilling.SetFilter("Charge End Date", '>=%1', BillingLine."Billing to");
Copy link
Contributor

Choose a reason for hiding this comment

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

There is a function named SetUsageDataBillingFilters. Can we use this one? Or perhaps even IsUsageDataBillingFound? In this case this loop can convert to a two liner.

Copy link
Author

Choose a reason for hiding this comment

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

Filtering is completely different.

Copy link
Contributor

Choose a reason for hiding this comment

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

That is a good point. Why is the filtering different? Currently these filters are wrong, and code seems to do nothing because it cannot find any records where an end date is before the start date:
image

Copy link
Author

Choose a reason for hiding this comment

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

How is charge end date before charge start date?
The idea is that one Usage Data Billing can have multiple BIlling Lines. Let's say yearly Usage data will have 12 billing lines with different Billing To, and we need to "catch" them all. Let's discuss it if needed.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, my fault. Sorry.

Comment on lines +287 to +289
UsageDataBilling.FilterDocumentWithLine("Service Partner"::Vendor, UsageBasedDocTypeConv.ConvertPurchaseDocTypeToUsageBasedBillingDocType(Rec."Document Type"), Rec."Document No.", Rec."Line No.");
if UsageDataBilling.IsEmpty() then
exit;
Copy link
Contributor

Choose a reason for hiding this comment

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

There is a built in function named FilterDocumentWithLine in Usage Data Billing table. Can we use this one instead?

Comment on lines +313 to +315
UsageDataBilling.FilterDocumentWithLine("Service Partner"::Customer, UsageBasedDocTypeConv.ConvertSalesDocTypeToUsageBasedBillingDocType(Rec."Document Type"), Rec."Document No.", Rec."Line No.");
if UsageDataBilling.IsEmpty() then
exit;
Copy link
Contributor

Choose a reason for hiding this comment

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

There is a built in function named FilterDocumentWithLine in Usage Data Billing table. Can we use this one instead? I would like to avoid unintentionally breaking whatever might have been programmed at any other BC client.

Comment on lines +325 to +331
local procedure ClearUsageDataBillingDocumentValues(var UsageDataBilling: Record "Usage Data Billing")
begin
if UsageDataBilling.FindSet() then
repeat
UsageDataBilling.SaveDocumentValues(UsageDataBilling."Document Type"::None, '', 0, 0);
until UsageDataBilling.Next() = 0;
end;
Copy link
Contributor

Choose a reason for hiding this comment

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

The same code exist in the function RemoveDocumentValuesFromUsageDataBilling. I think the function RemoveDocumentValuesFromUsageDataBilling should also call the function ClearUsageDataBillingDocumentValues

Copy link
Author

Choose a reason for hiding this comment

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

Done


[HandlerFunctions('ExchangeRateSelectionModalPageHandler,CreateCustomerBillingDocumentPageHandler,MessageHandler')]
[Test]
procedure DeleteUsageDataBillingLineWhenRelatedSalesInvoiceLineIsDeleted()
Copy link
Contributor

Choose a reason for hiding this comment

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

The function name is misleading as the Scenario states that some fields in Usage Data Billing are cleared but the record is not deleted. I guess also that the Test should not check if there are not Usage Data Billings for the Invoice Line but if the Usage Data Billing has been cleared.

Copy link
Author

@samra-singhammer samra-singhammer Sep 29, 2025

Choose a reason for hiding this comment

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

Scenario + test is updated.

Copy link
Contributor

Choose a reason for hiding this comment

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

Update of scenario and test is incorrect. This function does NOT delete the UsageDataBilling. It should only test clearing the "Billing Line Entry No.".


[HandlerFunctions('ExchangeRateSelectionModalPageHandler,CreateVendorBillingDocumentPageHandler,MessageHandler')]
[Test]
procedure DeleteUsageDataBillingLineWhenRelatedPurchLineIsDeleted()
Copy link
Contributor

Choose a reason for hiding this comment

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

The function name is misleading as the Scenario states that some fields in Usage Data Billing are cleared but the record is not deleted. Also the name of function is missing the word "Invoice". I guess also that the Test should not check if there are not Usage Data Billings for the Invoice Line but if the Usage Data Billing has been cleared.

Copy link
Author

Choose a reason for hiding this comment

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

Scenario + test is updated.

Copy link
Contributor

Choose a reason for hiding this comment

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

Update of scenario and test is incorrect. This function does NOT delete the UsageDataBilling. It should only test clearing the "Billing Line Entry No.".

@JesperSchulz JesperSchulz added the Finance GitHub request for Finance area label Sep 26, 2025
Comment on lines 453 to 456
UsageDataBilling.FilterOnServiceCommitment(SubscriptionLine);
UsageDataBilling.SetRange("Document Type", "Usage Based Billing Doc. Type"::None);
UsageDataBilling.SetFilter("Charge Start Date", '<=%1', BillingLine."Billing from");
UsageDataBilling.SetFilter("Charge End Date", '>=%1', BillingLine."Billing to");
Copy link
Contributor

Choose a reason for hiding this comment

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

That is a good point. Why is the filtering different? Currently these filters are wrong, and code seems to do nothing because it cannot find any records where an end date is before the start date:
image


[HandlerFunctions('ExchangeRateSelectionModalPageHandler,CreateCustomerBillingDocumentPageHandler,MessageHandler')]
[Test]
procedure DeleteUsageDataBillingLineWhenRelatedSalesInvoiceLineIsDeleted()
Copy link
Contributor

Choose a reason for hiding this comment

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

Update of scenario and test is incorrect. This function does NOT delete the UsageDataBilling. It should only test clearing the "Billing Line Entry No.".


[HandlerFunctions('ExchangeRateSelectionModalPageHandler,CreateVendorBillingDocumentPageHandler,MessageHandler')]
[Test]
procedure DeleteUsageDataBillingLineWhenRelatedPurchLineIsDeleted()
Copy link
Contributor

Choose a reason for hiding this comment

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

Update of scenario and test is incorrect. This function does NOT delete the UsageDataBilling. It should only test clearing the "Billing Line Entry No.".

djukicmilica
djukicmilica previously approved these changes Oct 6, 2025
@djukicmilica djukicmilica enabled auto-merge (squash) October 6, 2025 10:53
Comment on lines 458 to 473
if UsageDataBilling.FindSet() then
repeat
// Check if usage data period overlaps with billing line period
if IsPeriodsOverlapping(UsageDataBilling."Charge Start Date", UsageDataBilling."Charge End Date",
BillingLine."Billing from", BillingLine."Billing to") then begin
UsageDataBilling."Billing Line Entry No." := BillingLine."Entry No.";
UsageDataBilling.Modify(false);
end;
until UsageDataBilling.Next() = 0;
end;

local procedure IsPeriodsOverlapping(UsageStartDate: Date; UsageEndDate: Date; BillingStartDate: Date; BillingEndDate: Date): Boolean
begin
exit((UsageStartDate <= BillingEndDate) and (UsageEndDate >= BillingStartDate));
end;

Copy link
Contributor

Choose a reason for hiding this comment

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

This part could still be aligned with the function that serve the purpose of checking if there are Usage Data Billing connected to a Billing Line. The function is called SetUsageDataBillingFilters in Subscription Lines. Otherwise, we introduce code redundancy that can be avoided. The proposed solution fixes an issue but deserves a bit of optimization. Also, it is better to use ModifyAll after filters have been set.

auto-merge was automatically disabled October 6, 2025 15:10

Head branch was pushed to by a user without write access

JesperSchulz
JesperSchulz previously approved these changes Oct 6, 2025
@JesperSchulz JesperSchulz enabled auto-merge (squash) October 6, 2025 15:22
Copy link
Contributor

@AndersLarsenMicrosoft AndersLarsenMicrosoft left a comment

Choose a reason for hiding this comment

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

Please move ahead

@AndersLarsenMicrosoft
Copy link
Contributor

Please remove 'CorrectPostedPurchInvoice'
AA0137 Variable 'CorrectPostedPurchInvoice' is unused in 'DeleteUsageDataBillingLineWhenRelatedPurchCrMemoLineIsDeleted'.

var
PurchCrMemoHeader: Record "Purchase Header";
PurchInvHeader: Record "Purch. Inv. Header";
CorrectPostedPurchInvoice: Codeunit "Correct Posted Purch. Invoice";
Copy link
Contributor

Choose a reason for hiding this comment

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

Please remove this one. It have become an error after moving to BCAPPS

Copy link
Author

Choose a reason for hiding this comment

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

Removed.

auto-merge was automatically disabled October 9, 2025 07:29

Head branch was pushed to by a user without write access

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Finance GitHub request for Finance area From Fork Pull request is coming from a fork Linked Issue is linked to a Azure Boards work item

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants