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 @@ -54,7 +54,7 @@ codeunit 8021 "Text Management"
TextEditor.RunModal();
end;

local procedure ReadBlobText(RecRef: RecordRef; FieldNo: Integer): Text
internal procedure ReadBlobText(RecRef: RecordRef; FieldNo: Integer): Text
var
TempBlob: Codeunit "Temp Blob";
TypeHelper: Codeunit "Type Helper";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ page 8054 "Contract Types"
{
ToolTip = 'Specifies the default value for the associated field in the contract.';
}
field(AllowDiffCurrInVendUD; Rec."Allow Diff. Curr. in Vend. UD") { }
field(AllowDiffCurrInCustUD; Rec."Allow Diff. Curr. in Cust. UD") { }
field(NoOfTranslationsCtrl; FieldTranslation.GetNumberOfTranslations(Rec, Rec.FieldNo(Description)))
{
BlankZero = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,16 @@ table 8053 "Subscription Contract Type"
end;
end;
}
field(6; "Allow Diff. Curr. in Vend. UD"; Boolean)
{
Caption = 'Allow Different Currency in Vendor Usage Data';
ToolTip = 'Specifies whether vendor contracts of this type allow usage data with a currency different from the contract currency. If enabled, amounts will be automatically converted to the vendor contract currency when creating usage data billing. If disabled, an error will be raised when the usage data currency differs from the vendor contract currency.';
}
field(7; "Allow Diff. Curr. in Cust. UD"; Boolean)
{
Caption = 'Allow Different Currency in Customer Usage Data';
ToolTip = 'Specifies whether customer contracts of this type allow usage data with a currency different from the contract currency. If enabled, amounts will be automatically converted to the customer contract currency when creating usage data billing. If disabled, an error will be raised when the usage data currency differs from the customer contract currency.';
}
}

keys
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ codeunit 8075 "Extend Sub. Contract Mgt."
UsageDataSubscription2."Subscription Header No." := ServiceCommitment."Subscription Header No.";
UsageDataSubscription2."Subscription Line Entry No." := ServiceCommitment."Entry No.";
UsageDataSubscription2.Modify(false);
UsageDataSubscription2.UpdateServiceObjectNoForUsageDataGenericImport();
UsageDataSubscription2.UpdateSubscriptionHeaderNoInImportedData();
until UsageDataSubscription.Next() = 0;
end;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ permissionset 8001 "Sub. Billing Objects"
#if not CLEAN26
codeunit "Upgrade Subscription Billing" = X,
#endif
codeunit "Usage Based Billing Inst." = X,
codeunit "Usage Based Billing Mgmt." = X,
codeunit "Usage Based Contr. Subscribers" = X,
codeunit "Usage Based Doc. Type Conv." = X,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ page 8083 "Sales Serv. Comm. Archive List"
{
ToolTip = 'Specifies a code to identify this Subscription Package.';
}
field(UsageBasedBilling; Rec."Usage Based Billing") { }
field(UsageBasedPricing; Rec."Usage Based Pricing") { }
field(PricingUnitCostSurcharPerc; Rec."Pricing Unit Cost Surcharge %") { }
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,26 @@ table 8069 "Sales Sub. Line Archive"
AutoFormatExpression = '';
Caption = 'Unit Cost (LCY)';
}
field(8000; "Usage Based Billing"; Boolean)
{
Caption = 'Usage Based Billing';
ToolTip = 'Specifies whether usage data is used as the basis for billing via contracts.';
DataClassification = CustomerContent;
Copy link
Contributor

Choose a reason for hiding this comment

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

Redundant DataClassification set on a table, no need to set it on a field level

}
field(8001; "Usage Based Pricing"; Enum "Usage Based Pricing")
{
Caption = 'Usage Based Pricing';
ToolTip = 'Specifies the method for customer based pricing.';
DataClassification = CustomerContent;
Copy link
Contributor

Choose a reason for hiding this comment

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

Redundant DataClassification set on a table, no need to set it on a field level

}
field(8002; "Pricing Unit Cost Surcharge %"; Decimal)
{
Caption = 'Pricing Unit Cost Surcharge %';
ToolTip = 'Specifies the surcharge in percent for the debit-side price calculation, if a EK surcharge is to be used.';
DataClassification = CustomerContent;
Copy link
Contributor

Choose a reason for hiding this comment

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

Redundant DataClassification set on a table, no need to set it on a field level

AutoFormatType = 0;
DecimalPlaces = 0 : 5;
}
}

keys
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ page 8094 "Service Commitment Archive"
ToolTip = 'Specifies, whether the Planned Subscription Line has been created by a Price Update.';
Visible = false;
}
field(UsageBasedBilling; Rec."Usage Based Billing") { }
field(UsageBasedPricing; Rec."Usage Based Pricing") { }
field(PricingUnitCostSurcharPerc; Rec."Pricing Unit Cost Surcharge %") { }
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,29 @@ table 8073 "Subscription Line Archive"
Editable = false;
TableRelation = "Dimension Set Entry";
}
field(8000; "Usage Based Billing"; Boolean)
{
Caption = 'Usage Based Billing';
ToolTip = 'Specifies whether usage data is used as the basis for billing via contracts.';
DataClassification = CustomerContent;
Copy link
Contributor

Choose a reason for hiding this comment

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

Redundant DataClassification set on a table, no need to set it on a field level

Editable = false;
}
field(8001; "Usage Based Pricing"; Enum "Usage Based Pricing")
{
Caption = 'Usage Based Pricing';
ToolTip = 'Specifies the method for customer based pricing.';
DataClassification = CustomerContent;
Copy link
Contributor

Choose a reason for hiding this comment

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

Redundant DataClassification set on a table, no need to set it on a field level

Editable = false;
}
field(8002; "Pricing Unit Cost Surcharge %"; Decimal)
{
Caption = 'Pricing Unit Cost Surcharge %';
ToolTip = 'Specifies the surcharge in percent for the debit-side price calculation, if a EK surcharge is to be used.';
DataClassification = CustomerContent;
Copy link
Contributor

Choose a reason for hiding this comment

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

Redundant DataClassification set on a table, no need to set it on a field level

AutoFormatType = 0;
DecimalPlaces = 0 : 5;
Editable = false;
}
}
keys
{
Expand Down Expand Up @@ -355,6 +378,9 @@ table 8073 "Subscription Line Archive"
Rec."Unit Cost" := ServiceCommitment."Unit Cost";
Rec."Unit Cost (LCY)" := ServiceCommitment."Unit Cost (LCY)";
Rec.Closed := ServiceCommitment.Closed;
Rec."Usage Based Billing" := ServiceCommitment."Usage Based Billing";
Rec."Usage Based Pricing" := ServiceCommitment."Usage Based Pricing";
Rec."Pricing Unit Cost Surcharge %" := ServiceCommitment."Pricing Unit Cost Surcharge %";
OnAfterCopyFromSubscriptionLine(Rec, ServiceCommitment);
end;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
namespace Microsoft.SubscriptionBilling;

using System.Utilities;

codeunit 8023 "Create Usage Data Billing"
{
TableNo = "Usage Data Import";
Expand All @@ -17,38 +15,25 @@ codeunit 8023 "Create Usage Data Billing"
end;

local procedure Code()
var
UsageDataSupplier: Record "Usage Data Supplier";
begin
UsageDataImport.SetFilter("Processing Status", '<>%1', Enum::"Processing Status"::Closed);
if UsageDataImport.FindSet() then
repeat
CheckRetryFailedUsageLines();
if not RetryFailedUsageDataImport then
TestUsageDataImport();
UsageDataSupplier.Get(UsageDataImport."Supplier No.");
UsageDataProcessing := UsageDataSupplier.Type;
ValidateImportedData();
if not (UsageDataImport."Processing Status" = "Processing Status"::Error) then
FindAndProcessUsageDataImport();
CreateUsageDataBillingFromImport();
if not (UsageDataImport."Processing Status" = "Processing Status"::Error) then
SetUsageDataImportError();
UpdateImportStatus();
until UsageDataImport.Next() = 0;
end;

local procedure CheckRetryFailedUsageLines()
var
UsageDataBilling: Record "Usage Data Billing";
begin
UsageDataBilling.SetRange("Usage Data Import Entry No.", UsageDataImport."Entry No.");
if not UsageDataBilling.IsEmpty() then
if GuiAllowed then
if ConfirmManagement.GetResponse(StrSubstNo(RetryFailedUsageDataImportTxt, UsageDataImport."Entry No."), false) then
RetryFailedUsageDataImport := true;
end;

local procedure FindAndProcessUsageDataImport()
var
UsageDataSupplier: Record "Usage Data Supplier";
local procedure CreateUsageDataBillingFromImport()
begin
UsageDataSupplier.Get(UsageDataImport."Supplier No.");
UsageDataProcessing := UsageDataSupplier.Type;
UsageDataProcessing.FindAndProcessUsageDataImport(UsageDataImport);
UsageDataProcessing.CreateBillingData(UsageDataImport);
end;

internal procedure CollectServiceCommitments(var TempServiceCommitment: Record "Subscription Line" temporary; ServiceObjectNo: Code[20]; SubscriptionEndDate: Date)
Expand Down Expand Up @@ -76,21 +61,24 @@ codeunit 8023 "Create Usage Data Billing"
begin
UsageDataSupplier.Get(SupplierNo);

UsageDataBilling.InitFrom(UsageDataImportEntryNo, SubscriptionNo, ProductID, ProductName, BillingPeriodStartDate, BillingPeriodEndDate, UnitCost, NewQuantity, CostAmount, UnitPrice, NewAmount, CurrencyCode);
UsageDataBilling.InitFrom(UsageDataImportEntryNo, SubscriptionNo, ProductID, ProductName, BillingPeriodStartDate, BillingPeriodEndDate, NewQuantity);
UsageDataBilling."Supplier No." := SupplierNo;
UsageDataBilling."Subscription Header No." := TempServiceCommitment."Subscription Header No.";
UsageDataBilling.Partner := TempServiceCommitment.Partner;
UsageDataBilling."Subscription Header No." := TempServiceCommitment."Subscription Header No.";
UsageDataBilling."Subscription Contract No." := TempServiceCommitment."Subscription Contract No.";
UsageDataBilling."Subscription Contract Line No." := TempServiceCommitment."Subscription Contract Line No.";
UsageDataBilling."Subscription Header No." := TempServiceCommitment."Subscription Header No.";
UsageDataBilling."Subscription Line Entry No." := TempServiceCommitment."Entry No.";
UsageDataBilling."Subscription Line Description" := TempServiceCommitment.Description;
UsageDataBilling."Usage Base Pricing" := TempServiceCommitment."Usage Based Pricing";
UsageDataBilling."Pricing Unit Cost Surcharge %" := TempServiceCommitment."Pricing Unit Cost Surcharge %";
if UsageDataBilling.IsPartnerVendor() or not UsageDataSupplier."Unit Price from Import" then begin
UsageDataBilling."Unit Price" := 0;
UsageDataBilling.Amount := 0;
end;
if CurrencyCode = TempServiceCommitment."Currency Code" then
UsageDataBilling."Currency Code" := CurrencyCode
else
if UsageDataBilling.IsPartnerCustomer() then
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 create only one procedure AlignCurrencyCode, and then check there for the Partner type.

UsageDataBilling.AlignCustomerContractCurrency(TempServiceCommitment, CurrencyCode)
else
UsageDataBilling.AlignVendorContractCurrency(TempServiceCommitment, CurrencyCode);
UsageDataBilling.CalculateAmounts(UsageDataSupplier, CurrencyCode, UnitCost, CostAmount, UnitPrice, NewAmount);
UsageDataBilling.UpdateRebilling();
UsageDataBilling."Entry No." := 0;
UsageDataBilling.Insert(true);
Expand All @@ -117,23 +105,24 @@ codeunit 8023 "Create Usage Data Billing"
until ServiceCommitment.Next() = 0;
end;

local procedure TestUsageDataImport()
var
UsageDataSupplier: Record "Usage Data Supplier";
begin
UsageDataSupplier.Get(UsageDataImport."Supplier No.");
UsageDataProcessing := UsageDataSupplier.Type;
UsageDataProcessing.TestUsageDataImport(UsageDataImport);
end;

local procedure SetUsageDataImportError()
local procedure ValidateImportedData()
begin
UsageDataProcessing.SetUsageDataImportError(UsageDataImport);
UsageDataProcessing.ValidateImportedData(UsageDataImport);
end;

internal procedure GetRetryFailedUsageDataImport(): Boolean
local procedure UpdateImportStatus()
var
UsageDataBilling: Record "Usage Data Billing";
begin
exit(RetryFailedUsageDataImport);
UsageDataProcessing.UpdateImportStatus(UsageDataImport);
if UsageDataImport."Processing Status" = Enum::"Processing Status"::Error then
exit;
UsageDataBilling.SetRange("Usage Data Import Entry No.", UsageDataImport."Entry No.");
UsageDataBilling.SetRange("Processing Status", Enum::"Processing Status"::Error);
if not UsageDataBilling.IsEmpty() then begin
UsageDataImport.SetErrorReason(UsageDataLinesProcessingErr);
UsageDataImport.Modify(false);
end;
end;

[IntegrationEvent(false, false)]
Expand All @@ -153,7 +142,5 @@ codeunit 8023 "Create Usage Data Billing"

var
UsageDataImport: Record "Usage Data Import";
ConfirmManagement: Codeunit "Confirm Management";
RetryFailedUsageDataImportTxt: Label 'Usage Data Billing for Import %1 already exist. Do you want to try to create new entries for the failed Usage Data Generic Import only?', Comment = '%1=Usage Data Import Entry No.';
RetryFailedUsageDataImport: Boolean;
UsageDataLinesProcessingErr: Label 'Errors were detected when processing the usage data lines.';
}
Loading
Loading