Skip to content

Commit 1564c95

Browse files
authored
Invoice Details for "Unit Cost Surcharge" (#5280)
<!-- Thank you for submitting a Pull Request. If you're new to contributing to BCApps please read our pull request guideline below * https://github.com/microsoft/BCApps/Contributing.md --> #### Summary <!-- Provide a general summary of your changes --> - **Usage Data Billing** now contains both *Product ID* and *Product Name*. - Introduced a **setup field** to control whether the *Subscription Line Description* or *Product Name* is printed on a *Posted Sales Invoice* for **"Unit Cost Surcharge"** scenario. - Updated **Demo Data Creation** to prevent duplicate *Product Name* values when fields are imported via *Data Exchange Definition* in Usage-Based Billing. ⚠️ Note: This pull request requires a technical code review. Please hold off on approval until the technical review is completed by @samra-singhammer. #### Work Item(s) <!-- Add the issue number here after the #. The issue needs to be open and approved. Submitting PRs with no linked issues or unapproved issues is highly discouraged. --> Fixes #4485 Fixes [AB#614158](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/614158)
1 parent 740cd4a commit 1564c95

File tree

12 files changed

+367
-139
lines changed

12 files changed

+367
-139
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace Microsoft.SubscriptionBilling;
2+
3+
enum 8021 "Invoice Detail Origin"
4+
{
5+
Extensible = true;
6+
7+
value(0; "Product Name (default)")
8+
{
9+
Caption = 'Product Name (default)';
10+
}
11+
value(1; "Subscription Line")
12+
{
13+
Caption = 'Subscription Line';
14+
}
15+
}

src/Apps/W1/Subscription Billing/App/Base/Pages/ServiceContractSetup.Page.al

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,15 @@ page 8051 "Service Contract Setup"
8282
{
8383
ToolTip = 'Specifies which customer information (name) is transferred to collective invoices. This setting is applies for collective invoices only.';
8484
}
85+
group("Usage Data")
86+
{
87+
Caption = 'Usage Data';
88+
89+
field("Invoice Desc. (Surcharge)"; Rec."Invoice Desc. (Surcharge)")
90+
{
91+
ToolTip = 'Specifies the origin of the invoice details'' description for usage data to be charged as Unit Cost Surcharge.';
92+
}
93+
}
8594
group(ArrangeTexts)
8695
{
8796
Caption = 'Arrange Texts';

src/Apps/W1/Subscription Billing/App/Base/Tables/SubscriptionContractSetup.Table.al

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ table 8051 "Subscription Contract Setup"
7676
Caption = 'Dimension Code for Customer Subscription Contract';
7777
TableRelation = Dimension;
7878
}
79+
field(30; "Invoice Desc. (Surcharge)"; Enum "Invoice Detail Origin")
80+
{
81+
Caption = 'Invoice Description (Surcharge)';
82+
}
7983
field(59; "Default Period Calculation"; enum "Period Calculation")
8084
{
8185
Caption = 'Default Period Calculation';

src/Apps/W1/Subscription Billing/App/Billing/Codeunits/SubContractBillingPrintout.Codeunit.al

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ codeunit 8064 "Sub. Contract Billing Printout"
4848
TempJobLedgerEntryBuffer."Document Date" := UsageDataBilling."Charge Start Date";
4949
TempJobLedgerEntryBuffer."Posting Date" := UsageDataBilling."Charge End Date";
5050
TempJobLedgerEntryBuffer.Quantity := UsageDataBilling.Quantity;
51-
TempJobLedgerEntryBuffer.Description := UsageDataBilling."Subscription Description";
51+
TempJobLedgerEntryBuffer.Description := UsageDataBilling.GetPrintoutDescription();
5252
TempJobLedgerEntryBuffer."External Document No." := UsageDataBilling."Subscription Contract No.";
5353
TempJobLedgerEntryBuffer."Resource Group No." := SalesInvoiceHeader."Sell-to Customer No.";
5454
if SalesInvoiceHeader."Sub. Contract Detail Overview" = Enum::"Contract Detail Overview"::Complete then begin

src/Apps/W1/Subscription Billing/App/Usage Based Billing/Codeunits/CreateUsageDataBilling.Codeunit.al

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,24 +57,26 @@ codeunit 8023 "Create Usage Data Billing"
5757
OnAfterCollectServiceCommitments(TempServiceCommitment, ServiceObjectNo, SubscriptionEndDate);
5858
end;
5959

60-
internal procedure CreateUsageDataBillingFromTempServiceCommitments(var TempServiceCommitment: Record "Subscription Line"; SupplierNo: Code[20]; UsageDataImportEntryNo: Integer; ServiceObjectNo: Code[20]; BillingPeriodStartDate: Date;
61-
BillingPeriodEndDate: Date; UnitCost: Decimal; NewQuantity: Decimal; CostAmount: Decimal; UnitPrice: Decimal; NewAmount: Decimal; CurrencyCode: Code[10])
60+
internal procedure CreateUsageDataBillingFromTempServiceCommitments(
61+
var TempServiceCommitment: Record "Subscription Line"; SupplierNo: Code[20]; UsageDataImportEntryNo: Integer; ServiceObjectNo: Code[20]; ProductID: Text[80]; ProductName: Text[100];
62+
BillingPeriodStartDate: Date; BillingPeriodEndDate: Date; UnitCost: Decimal; NewQuantity: Decimal; CostAmount: Decimal; UnitPrice: Decimal; NewAmount: Decimal; CurrencyCode: Code[10])
6263
begin
6364
repeat
64-
CreateUsageDataBillingFromTempServiceCommitment(TempServiceCommitment, SupplierNo, UsageDataImportEntryNo, ServiceObjectNo, BillingPeriodStartDate, BillingPeriodEndDate, UnitCost, NewQuantity, CostAmount, UnitPrice, NewAmount, CurrencyCode);
65+
CreateUsageDataBillingFromTempServiceCommitment(TempServiceCommitment, SupplierNo, UsageDataImportEntryNo, ServiceObjectNo, ProductID, ProductName, BillingPeriodStartDate, BillingPeriodEndDate, UnitCost, NewQuantity, CostAmount, UnitPrice, NewAmount, CurrencyCode);
6566
until TempServiceCommitment.Next() = 0;
6667
OnAfterCreateUsageDataBillingFromTempSubscriptionLines(TempServiceCommitment);
6768
end;
6869

69-
local procedure CreateUsageDataBillingFromTempServiceCommitment(var TempServiceCommitment: Record "Subscription Line"; SupplierNo: Code[20]; UsageDataImportEntryNo: Integer; ServiceObjectNo: Code[20]; BillingPeriodStartDate: Date;
70-
BillingPeriodEndDate: Date; UnitCost: Decimal; NewQuantity: Decimal; CostAmount: Decimal; UnitPrice: Decimal; NewAmount: Decimal; CurrencyCode: Code[10])
70+
local procedure CreateUsageDataBillingFromTempServiceCommitment(
71+
var TempServiceCommitment: Record "Subscription Line"; SupplierNo: Code[20]; UsageDataImportEntryNo: Integer; SubscriptionNo: Code[20]; ProductID: Text[80]; ProductName: Text[100];
72+
BillingPeriodStartDate: Date; BillingPeriodEndDate: Date; UnitCost: Decimal; NewQuantity: Decimal; CostAmount: Decimal; UnitPrice: Decimal; NewAmount: Decimal; CurrencyCode: Code[10])
7173
var
7274
UsageDataBilling: Record "Usage Data Billing";
7375
UsageDataSupplier: Record "Usage Data Supplier";
7476
begin
7577
UsageDataSupplier.Get(SupplierNo);
7678

77-
UsageDataBilling.InitFrom(UsageDataImportEntryNo, ServiceObjectNo, BillingPeriodStartDate, BillingPeriodEndDate, UnitCost, NewQuantity, CostAmount, UnitPrice, NewAmount, CurrencyCode);
79+
UsageDataBilling.InitFrom(UsageDataImportEntryNo, SubscriptionNo, ProductID, ProductName, BillingPeriodStartDate, BillingPeriodEndDate, UnitCost, NewQuantity, CostAmount, UnitPrice, NewAmount, CurrencyCode);
7880
UsageDataBilling."Supplier No." := SupplierNo;
7981
UsageDataBilling."Subscription Header No." := TempServiceCommitment."Subscription Header No.";
8082
UsageDataBilling.Partner := TempServiceCommitment.Partner;

src/Apps/W1/Subscription Billing/App/Usage Based Billing/Codeunits/GenericConnectorProcessing.Codeunit.al

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,19 @@ codeunit 8033 "Generic Connector Processing" implements "Usage Data Processing"
205205
SetUsageDataGenericImportError('');
206206
if not CheckServiceCommitments(TempServiceCommitment) then
207207
exit;
208-
CreateUsageDataBilling.CreateUsageDataBillingFromTempServiceCommitments(TempServiceCommitment, UsageDataImport."Supplier No.", UsageDataGenericImportGlobal."Usage Data Import Entry No.", UsageDataGenericImportGlobal."Subscription Header No.", UsageDataGenericImportGlobal."Billing Period Start Date",
209-
UsageDataGenericImportGlobal."Billing Period End Date", UsageDataGenericImportGlobal.Cost, UsageDataGenericImportGlobal.Quantity,
210-
UsageDataGenericImportGlobal."Cost Amount", UsageDataGenericImportGlobal.Price, UsageDataGenericImportGlobal.Amount, UsageDataGenericImportGlobal.GetCurrencyCode());
208+
CreateUsageDataBilling.CreateUsageDataBillingFromTempServiceCommitments(
209+
TempServiceCommitment, UsageDataImport."Supplier No.",
210+
UsageDataGenericImportGlobal."Usage Data Import Entry No.",
211+
UsageDataGenericImportGlobal."Subscription Header No.",
212+
UsageDataGenericImportGlobal."Product ID",
213+
UsageDataGenericImportGlobal."Product Name",
214+
UsageDataGenericImportGlobal."Billing Period Start Date",
215+
UsageDataGenericImportGlobal."Billing Period End Date",
216+
UsageDataGenericImportGlobal.Cost, UsageDataGenericImportGlobal.Quantity,
217+
UsageDataGenericImportGlobal."Cost Amount",
218+
UsageDataGenericImportGlobal.Price,
219+
UsageDataGenericImportGlobal.Amount,
220+
UsageDataGenericImportGlobal.GetCurrencyCode());
211221
until UsageDataGenericImportGlobal.Next() = 0
212222
else begin
213223
UsageDataImport.SetErrorReason(StrSubstNo(NoDataFoundErr, UsageDataImport."Processing Step"));

src/Apps/W1/Subscription Billing/App/Usage Based Billing/Pages/UsageDataBillings.Page.al

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ page 8035 "Usage Data Billings"
5555
{
5656
ToolTip = 'Specifies the Subscription Line for which the usage data is billed.';
5757
}
58+
field("Product ID"; Rec."Product ID") { }
59+
field("Product Name"; Rec."Product Name") { }
5860
field("Processing Date"; Rec."Processing Date")
5961
{
6062
ToolTip = 'Specifies the date of processing.';

src/Apps/W1/Subscription Billing/App/Usage Based Billing/Tables/UsageDataBilling.Table.al

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,16 @@ table 8006 "Usage Data Billing"
277277
{
278278
Caption = 'Rebilling';
279279
}
280+
field(35; "Product ID"; Text[80])
281+
{
282+
Caption = 'Product Id';
283+
ToolTip = 'Specifies the unique ID of the product for this subscription with the supplier.';
284+
}
285+
field(36; "Product Name"; Text[100])
286+
{
287+
Caption = 'Product Name';
288+
ToolTip = 'Specifies the vendor''s product name for this subscription.';
289+
}
280290
}
281291
keys
282292
{
@@ -349,20 +359,22 @@ table 8006 "Usage Data Billing"
349359
end;
350360
end;
351361

352-
internal procedure InitFrom(UsageDataImportEntryNo: Integer; ServiceObjectNo: Code[20]; BillingPeriodStartDate: Date;
353-
BillingPeriodEndDate: Date; UnitCost: Decimal; NewQuantity: Decimal; CostAmount: Decimal; UnitPrice: Decimal;
354-
NewAmount: Decimal; CurrencyCode: Code[10])
362+
internal procedure InitFrom(UsageDataImportEntryNo: Integer; SubscriptionHeaderNo: Code[20]; ProductID: Text[80]; ProductName: Text[100];
363+
BillingPeriodStartDate: Date; BillingPeriodEndDate: Date; UnitCost: Decimal; NewQuantity: Decimal; CostAmount: Decimal;
364+
UnitPrice: Decimal; NewAmount: Decimal; CurrencyCode: Code[10])
355365
begin
356366
Rec.Init();
357367
Rec."Entry No." := 0;
358368
Rec."Usage Data Import Entry No." := UsageDataImportEntryNo;
359-
Rec."Subscription Header No." := ServiceObjectNo;
369+
Rec."Subscription Header No." := SubscriptionHeaderNo;
370+
Rec."Product ID" := ProductID;
371+
Rec."Product Name" := ProductName;
360372
Rec."Charge Start Date" := BillingPeriodStartDate;
361373
Rec."Charge End Date" := BillingPeriodEndDate;
362374
Rec."Unit Cost" := UnitCost;
363375
Rec.Quantity := NewQuantity;
364376
if CostAmount = 0 then
365-
Rec."Cost Amount" := NewQuantity * unitCost
377+
Rec."Cost Amount" := NewQuantity * UnitCost
366378
else
367379
Rec."Cost Amount" := CostAmount;
368380
Rec."Unit Price" := UnitPrice;
@@ -696,11 +708,41 @@ table 8006 "Usage Data Billing"
696708
exit((Rec."Document Type" <> "Usage Based Billing Doc. Type"::None) and (Rec."Document No." <> ''));
697709
end;
698710

711+
internal procedure GetPrintoutDescription() Description: Text[100]
712+
begin
713+
if ShouldPrintProductName() then
714+
Description := "Product Name"
715+
else
716+
Description := "Subscription Description";
717+
OnAfterGetPrintoutDescription(Rec, Description);
718+
end;
719+
720+
internal procedure ShouldPrintProductName() Result: Boolean
721+
var
722+
ServiceContractSetup: Record "Subscription Contract Setup";
723+
begin
724+
ServiceContractSetup.Get();
725+
Result :=
726+
("Usage Base Pricing" = Enum::"Usage Based Pricing"::"Unit Cost Surcharge") and
727+
(ServiceContractSetup."Invoice Desc. (Surcharge)" = Enum::"Invoice Detail Origin"::"Product Name (default)");
728+
OnAfterShouldPrintProductName(Rec, Result);
729+
end;
730+
699731
[IntegrationEvent(false, false)]
700732
local procedure OnAfterSaveDocumentValues(UsageDateBilling: Record "Usage Data Billing")
701733
begin
702734
end;
703735

736+
[IntegrationEvent(false, false)]
737+
local procedure OnAfterGetPrintoutDescription(Rec: Record "Usage Data Billing"; var Description: Text[100])
738+
begin
739+
end;
740+
741+
[IntegrationEvent(false, false)]
742+
local procedure OnAfterShouldPrintProductName(Rec: Record "Usage Data Billing"; var Result: Boolean)
743+
begin
744+
end;
745+
704746
var
705747
UsageBasedDocTypeConv: Codeunit "Usage Based Doc. Type Conv.";
706748
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<root>
3+
<DataExchDef Code="USAGE-GENERIC-US" Name="Usage Data Generic (US format)" Type="3" ReadingWritingXMLport="1220" HeaderLines="1" ColumnSeparator="2" FileEncoding="1" FileType="1" LineSeparator="0">
4+
<DataExchLineDef LineType="0" Code="LINES" Name="Usage data" ColumnCount="15">
5+
<DataExchColumnDef ColumnNo="1" Name="Customer ID" Show="false" DataType="0" TextPaddingRequired="false" Justification="0" UseNodeNameAsValue="false" BlankZero="false" ExportIfNotBlank="false" />
6+
<DataExchColumnDef ColumnNo="2" Name="Customer Name" Show="false" DataType="0" TextPaddingRequired="false" Justification="0" UseNodeNameAsValue="false" BlankZero="false" ExportIfNotBlank="false" />
7+
<DataExchColumnDef ColumnNo="3" Name="Subscription ID" Show="false" DataType="0" TextPaddingRequired="false" Justification="0" UseNodeNameAsValue="false" BlankZero="false" ExportIfNotBlank="false" />
8+
<DataExchColumnDef ColumnNo="4" Name="Product ID" Show="false" DataType="0" TextPaddingRequired="false" Justification="0" UseNodeNameAsValue="false" BlankZero="false" ExportIfNotBlank="false" />
9+
<DataExchColumnDef ColumnNo="5" Name="Product Name" Show="false" DataType="0" TextPaddingRequired="false" Justification="0" UseNodeNameAsValue="false" BlankZero="false" ExportIfNotBlank="false" />
10+
<DataExchColumnDef ColumnNo="6" Name="Subscription Start Date" Show="false" DataType="1" DataFormat="MM-dd-yyyy" DataFormattingCulture="en-US" TextPaddingRequired="false" Justification="0" UseNodeNameAsValue="false" BlankZero="false" ExportIfNotBlank="false" />
11+
<DataExchColumnDef ColumnNo="7" Name="Subscription End Date" Show="false" DataType="1" DataFormat="MM-dd-yyyy" DataFormattingCulture="en-US" TextPaddingRequired="false" Justification="0" UseNodeNameAsValue="false" BlankZero="false" ExportIfNotBlank="false" />
12+
<DataExchColumnDef ColumnNo="8" Name="Billing Period Start Date" Show="false" DataType="1" DataFormat="MM-dd-yyyy" DataFormattingCulture="en-US" TextPaddingRequired="false" Justification="0" UseNodeNameAsValue="false" BlankZero="false" ExportIfNotBlank="false" />
13+
<DataExchColumnDef ColumnNo="9" Name="Billing Period End Date" Show="false" DataType="1" DataFormat="MM-dd-yyyy" DataFormattingCulture="en-US" TextPaddingRequired="false" Justification="0" UseNodeNameAsValue="false" BlankZero="false" ExportIfNotBlank="false" />
14+
<DataExchColumnDef ColumnNo="10" Name="Quantity" Show="false" DataType="2" DataFormattingCulture="en-US" TextPaddingRequired="false" Justification="0" UseNodeNameAsValue="false" BlankZero="false" ExportIfNotBlank="false" />
15+
<DataExchColumnDef ColumnNo="11" Name="Unit Cost" Show="false" DataType="2" DataFormattingCulture="en-US" TextPaddingRequired="false" Justification="0" UseNodeNameAsValue="false" BlankZero="false" ExportIfNotBlank="false" />
16+
<DataExchColumnDef ColumnNo="12" Name="Unit Price" Show="false" DataType="2" DataFormattingCulture="en-US" TextPaddingRequired="false" Justification="0" UseNodeNameAsValue="false" BlankZero="false" ExportIfNotBlank="false" />
17+
<DataExchColumnDef ColumnNo="13" Name="Cost Amount" Show="false" DataType="2" DataFormattingCulture="en-US" TextPaddingRequired="false" Justification="0" UseNodeNameAsValue="false" BlankZero="false" ExportIfNotBlank="false" />
18+
<DataExchColumnDef ColumnNo="14" Name="Amount" Show="false" DataType="2" DataFormattingCulture="en-US" TextPaddingRequired="false" Justification="0" UseNodeNameAsValue="false" BlankZero="false" ExportIfNotBlank="false" />
19+
<DataExchColumnDef ColumnNo="15" Name="Currency" Show="false" DataType="0" TextPaddingRequired="false" Justification="0" UseNodeNameAsValue="false" BlankZero="false" ExportIfNotBlank="false" />
20+
<DataExchMapping TableId="8018" Name="Usage data" MappingCodeunit="8030">
21+
<DataExchFieldMapping ColumnNo="1" FieldID="7" OverwriteValue="true" />
22+
<DataExchFieldMapping ColumnNo="2" FieldID="8" OverwriteValue="true" />
23+
<DataExchFieldMapping ColumnNo="3" FieldID="10" OverwriteValue="true" />
24+
<DataExchFieldMapping ColumnNo="4" FieldID="17" OverwriteValue="true" />
25+
<DataExchFieldMapping ColumnNo="5" FieldID="18" OverwriteValue="true" />
26+
<DataExchFieldMapping ColumnNo="6" FieldID="13" />
27+
<DataExchFieldMapping ColumnNo="7" FieldID="14" />
28+
<DataExchFieldMapping ColumnNo="8" FieldID="15" />
29+
<DataExchFieldMapping ColumnNo="9" FieldID="16" />
30+
<DataExchFieldMapping ColumnNo="10" FieldID="21" />
31+
<DataExchFieldMapping ColumnNo="11" FieldID="19" />
32+
<DataExchFieldMapping ColumnNo="12" FieldID="20" />
33+
<DataExchFieldMapping ColumnNo="13" FieldID="27" />
34+
<DataExchFieldMapping ColumnNo="14" FieldID="24" />
35+
<DataExchFieldMapping ColumnNo="15" FieldID="25" />
36+
</DataExchMapping>
37+
</DataExchLineDef>
38+
</DataExchDef>
39+
</root>

0 commit comments

Comments
 (0)