diff --git a/src/Apps/W1/Shopify/App/src/Document Links/Codeunits/ShpfyDocumentLinkMgt.Codeunit.al b/src/Apps/W1/Shopify/App/src/Document Links/Codeunits/ShpfyDocumentLinkMgt.Codeunit.al
index 2c2830ca09..c20f5551dd 100644
--- a/src/Apps/W1/Shopify/App/src/Document Links/Codeunits/ShpfyDocumentLinkMgt.Codeunit.al
+++ b/src/Apps/W1/Shopify/App/src/Document Links/Codeunits/ShpfyDocumentLinkMgt.Codeunit.al
@@ -64,6 +64,16 @@ codeunit 30262 "Shpfy Document Link Mgt."
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Sales-Post", 'OnAfterPostSalesDoc', '', true, false)]
local procedure OnAfterSalesPosting(var SalesHeader: Record "Sales Header"; PreviewMode: Boolean; SalesShptHdrNo: Code[20]; SalesInvHdrNo: Code[20]; RetRcpHdrNo: Code[20]; SalesCrMemoHdrNo: Code[20])
+ var
+ ShpfyAutoPostTransactions: Codeunit "Shpfy Auto Post Transactions";
+ begin
+ CreateDocLinksToBCDocs(SalesHeader, PreviewMode, SalesShptHdrNo, SalesInvHdrNo, RetRcpHdrNo, SalesCrMemoHdrNo);
+
+ Commit(); // Ensure Doc. Link To Doc. creation is committed before running the automatic transaction posting.
+ ShpfyAutoPostTransactions.AutoPostTransactions(SalesInvHdrNo, SalesCrMemoHdrNo);
+ end;
+
+ local procedure CreateDocLinksToBCDocs(var SalesHeader: Record "Sales Header"; PreviewMode: Boolean; SalesShptHdrNo: Code[20]; SalesInvHdrNo: Code[20]; RetRcpHdrNo: Code[20]; SalesCrMemoHdrNo: Code[20])
var
SalesShipmentHeader: Record "Sales Shipment Header";
SalesInvoiceLine: Record "Sales Invoice Line";
diff --git a/src/Apps/W1/Shopify/App/src/PermissionSets/ShpfyObjects.PermissionSet.al b/src/Apps/W1/Shopify/App/src/PermissionSets/ShpfyObjects.PermissionSet.al
index 52af1b5cba..aa065d2006 100644
--- a/src/Apps/W1/Shopify/App/src/PermissionSets/ShpfyObjects.PermissionSet.al
+++ b/src/Apps/W1/Shopify/App/src/PermissionSets/ShpfyObjects.PermissionSet.al
@@ -103,6 +103,8 @@ permissionset 30104 "Shpfy - Objects"
report "Shpfy Translator" = X,
codeunit "Company Details Checklist Item" = X,
codeunit "Shpfy Authentication Mgt." = X,
+ codeunit "Shpfy Auto Gen. Jnl.-Post" = X,
+ codeunit "Shpfy Auto Post Transactions" = X,
codeunit "Shpfy Background Syncs" = X,
codeunit "Shpfy Balance Today" = X,
codeunit "Shpfy Base64" = X,
@@ -441,6 +443,7 @@ permissionset 30104 "Shpfy - Objects"
page "Shpfy Customers" = X,
page "Shpfy Data Capture List" = X,
page "Shpfy Disputes" = X,
+ page "Shpfy Filter Transactions" = X,
page "Shpfy Fulfillment Order Card" = X,
page "Shpfy Fulfillment Order Lines" = X,
page "Shpfy Fulfillment Orders" = X,
diff --git a/src/Apps/W1/Shopify/App/src/Transactions/Codeunits/ShpfyAutoGenJnlPost.Codeunit.al b/src/Apps/W1/Shopify/App/src/Transactions/Codeunits/ShpfyAutoGenJnlPost.Codeunit.al
new file mode 100644
index 0000000000..91cebf76ae
--- /dev/null
+++ b/src/Apps/W1/Shopify/App/src/Transactions/Codeunits/ShpfyAutoGenJnlPost.Codeunit.al
@@ -0,0 +1,29 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace Microsoft.Integration.Shopify;
+
+using Microsoft.Finance.GeneralLedger.Journal;
+using Microsoft.Finance.GeneralLedger.Posting;
+
+///
+/// Codeunit Shpfy Auto Gen. Jnl.-Post (ID 30422).
+///
+codeunit 30422 "Shpfy Auto Gen. Jnl.-Post"
+{
+ EventSubscriberInstance = Manual;
+
+ [EventSubscriber(ObjectType::Codeunit, Codeunit::"Gen. Jnl.-Post", 'OnBeforeCode', '', false, false)]
+ local procedure OnBeforeCode(var GenJournalLine: Record "Gen. Journal Line"; var HideDialog: Boolean)
+ begin
+ HideDialog := true;
+ end;
+
+ [EventSubscriber(ObjectType::Codeunit, Codeunit::"Gen. Jnl.-Post", 'OnBeforeShowPostResultMessage', '', false, false)]
+ local procedure OnBeforeShowPostResultMessage(var GenJnlLine: Record "Gen. Journal Line"; TempJnlBatchName: Code[10]; var IsHandled: Boolean)
+ begin
+ IsHandled := true;
+ end;
+}
diff --git a/src/Apps/W1/Shopify/App/src/Transactions/Codeunits/ShpfyAutoPostTransactions.Codeunit.al b/src/Apps/W1/Shopify/App/src/Transactions/Codeunits/ShpfyAutoPostTransactions.Codeunit.al
new file mode 100644
index 0000000000..ac8dbeb6d1
--- /dev/null
+++ b/src/Apps/W1/Shopify/App/src/Transactions/Codeunits/ShpfyAutoPostTransactions.Codeunit.al
@@ -0,0 +1,105 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace Microsoft.Integration.Shopify;
+
+using Microsoft.Finance.GeneralLedger.Journal;
+using Microsoft.Finance.GeneralLedger.Posting;
+using Microsoft.Sales.History;
+
+///
+/// Codeunit Shpfy Auto Post Transactions (ID 30236).
+///
+codeunit 30236 "Shpfy Auto Post Transactions"
+{
+ Access = Internal;
+
+ internal procedure AutoPostTransactions(SalesInvoiceHeaderNo: Code[20]; SalesCrMemoHeaderNo: Code[20])
+ begin
+ if SalesInvoiceHeaderNo <> '' then
+ PostOrderTransaction(SalesInvoiceHeaderNo);
+ if SalesCrMemoHeaderNo <> '' then
+ PostRefundTransaction(SalesCrMemoHeaderNo);
+ end;
+
+ local procedure PostOrderTransaction(SalesInvoiceHeaderNo: Code[20])
+ var
+ SalesInvoiceHeader: Record "Sales Invoice Header";
+ OrderTransaction: Record "Shpfy Order Transaction";
+ begin
+ if not SalesInvoiceHeader.Get(SalesInvoiceHeaderNo) then
+ exit;
+
+ if SalesInvoiceHeader."Shpfy Order Id" = 0 then
+ exit;
+
+ OrderTransaction.SetRange("Shopify Order Id", SalesInvoiceHeader."Shpfy Order Id");
+ OrderTransaction.SetFilter(Type, '%1|%2', OrderTransaction.Type::Capture, OrderTransaction.Type::Sale);
+ PostTransaction(OrderTransaction, SalesInvoiceHeader."Posting Date");
+ end;
+
+ local procedure PostRefundTransaction(SalesCrMemoHeaderNo: Code[20])
+ var
+ SalesCrMemoHeader: Record "Sales Cr.Memo Header";
+ OrderTransaction: Record "Shpfy Order Transaction";
+ begin
+ if not SalesCrMemoHeader.Get(SalesCrMemoHeaderNo) then
+ exit;
+
+ if SalesCrMemoHeader."Shpfy Refund Id" = 0 then
+ exit;
+
+ OrderTransaction.SetRange("Refund Id", SalesCrMemoHeader."Shpfy Refund Id");
+ OrderTransaction.SetRange(Type, OrderTransaction.Type::Refund);
+ PostTransaction(OrderTransaction, SalesCrMemoHeader."Posting Date");
+ end;
+
+ local procedure PostTransaction(var OrderTransaction: Record "Shpfy Order Transaction"; PostingDate: Date)
+ begin
+ OrderTransaction.SetRange(Status, OrderTransaction.Status::Success);
+ OrderTransaction.SetRange(Used, false);
+ if OrderTransaction.FindSet() then
+ repeat
+ if ShouldAutoPost(OrderTransaction) then
+ CreateAndPostJournalLine(OrderTransaction, PostingDate);
+ until OrderTransaction.Next() = 0;
+ end;
+
+ local procedure ShouldAutoPost(OrderTransaction: Record "Shpfy Order Transaction"): Boolean
+ var
+ PaymentMethodMapping: Record "Shpfy Payment Method Mapping";
+ begin
+ if not PaymentMethodMapping.Get(OrderTransaction.Shop, OrderTransaction.Gateway, OrderTransaction."Credit Card Company") then
+ exit(false);
+
+ if not PaymentMethodMapping."Post Automatically" then
+ exit(false);
+
+ if (PaymentMethodMapping."Auto-Post Jnl. Template" = '') or
+ (PaymentMethodMapping."Auto-Post Jnl. Batch" = '') then
+ exit(false);
+
+ exit(true);
+ end;
+
+ local procedure CreateAndPostJournalLine(var OrderTransaction: Record "Shpfy Order Transaction"; PostingDate: Date)
+ var
+ GenJournalLine: Record "Gen. Journal Line";
+ PaymentMethodMapping: Record "Shpfy Payment Method Mapping";
+ SuggestPayments: Report "Shpfy Suggest Payments";
+ AutoGenJnlPost: Codeunit "Shpfy Auto Gen. Jnl.-Post";
+ begin
+ PaymentMethodMapping.Get(OrderTransaction.Shop, OrderTransaction.Gateway, OrderTransaction."Credit Card Company");
+ SuggestPayments.SetJournalParameters(PaymentMethodMapping."Auto-Post Jnl. Template", PaymentMethodMapping."Auto-Post Jnl. Batch", PostingDate);
+ SuggestPayments.GetOrderTransactions(OrderTransaction);
+ SuggestPayments.CreateGeneralJournalLines();
+ GenJournalLine.SetRange("Shpfy Transaction Id", OrderTransaction."Shopify Transaction Id");
+ if GenJournalLine.FindFirst() then begin
+ BindSubscription(AutoGenJnlPost);
+ GenJournalLine.SendToPosting(Codeunit::"Gen. Jnl.-Post");
+ UnbindSubscription(AutoGenJnlPost);
+ end;
+ end;
+}
\ No newline at end of file
diff --git a/src/Apps/W1/Shopify/App/src/Transactions/Pages/ShpfyFilterTransactions.Page.al b/src/Apps/W1/Shopify/App/src/Transactions/Pages/ShpfyFilterTransactions.Page.al
new file mode 100644
index 0000000000..be7153dba0
--- /dev/null
+++ b/src/Apps/W1/Shopify/App/src/Transactions/Pages/ShpfyFilterTransactions.Page.al
@@ -0,0 +1,67 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace Microsoft.Integration.Shopify;
+
+///
+/// Page Shpfy Filter Transactions (ID 30176).
+///
+page 30176 "Shpfy Filter Transactions"
+{
+ Caption = 'Filter Postable Transactions';
+ PageType = StandardDialog;
+ ApplicationArea = All;
+
+ layout
+ {
+ area(Content)
+ {
+ field(Gateway; Gateway)
+ {
+ Caption = 'Gateway';
+ ToolTip = 'Specifies the transaction gateway to filter transactions by. Leave blank to include all gateways.';
+ Editable = false;
+
+ trigger OnAssistEdit()
+ var
+ PaymentMethodMapping: Record "Shpfy Payment Method Mapping";
+ begin
+ PaymentMethodMapping.SetRange("Post Automatically", true);
+ if Page.RunModal(0, PaymentMethodMapping) = Action::LookupOK then begin
+ ShopCode := PaymentMethodMapping."Shop Code";
+ Gateway := PaymentMethodMapping.Gateway;
+ CreditCardCompany := PaymentMethodMapping."Credit Card Company";
+ end;
+ end;
+ }
+ field(StartDate; StartDate)
+ {
+ Caption = 'Start Date';
+ ToolTip = 'Specifies the earliest transaction creation date to include in the filter. Leave blank to include all transactions from the beginning.';
+ }
+ field(EndDate; EndDate)
+ {
+ Caption = 'End Date';
+ ToolTip = 'Specifies the latest transaction creation date to include in the filter. Leave blank to include all transactions.';
+ }
+ }
+ }
+
+ var
+ ShopCode: Code[20];
+ Gateway: Text[30];
+ CreditCardCompany: Text[50];
+ StartDate: Date;
+ EndDate: Date;
+
+ internal procedure GetParameters(var NewShopCode: Code[20]; var NewGateway: Text[30]; var NewCreditCardCompany: Text[50]; var NewStartDate: DateTime; var NewEndDate: DateTime)
+ begin
+ NewShopCode := ShopCode;
+ NewGateway := Gateway;
+ NewCreditCardCompany := CreditCardCompany;
+ NewStartDate := CreateDateTime(StartDate, 0T);
+ NewEndDate := CreateDateTime(EndDate, 0T);
+ end;
+}
\ No newline at end of file
diff --git a/src/Apps/W1/Shopify/App/src/Transactions/Pages/ShpfyPaymentMethodsMapping.Page.al b/src/Apps/W1/Shopify/App/src/Transactions/Pages/ShpfyPaymentMethodsMapping.Page.al
index e5cab053ed..e4f85863b1 100644
--- a/src/Apps/W1/Shopify/App/src/Transactions/Pages/ShpfyPaymentMethodsMapping.Page.al
+++ b/src/Apps/W1/Shopify/App/src/Transactions/Pages/ShpfyPaymentMethodsMapping.Page.al
@@ -37,6 +37,25 @@ page 30132 "Shpfy Payment Methods Mapping"
ApplicationArea = All;
ToolTip = 'Specifies the corresponding payment method in D365BC.';
}
+ field(PostAutomatically; Rec."Post Automatically")
+ {
+ ApplicationArea = All;
+ ToolTip = 'Specifies whether payment transactions using this gateway should be automatically posted when the related invoice or credit memo is posted.';
+ }
+ field(AutoPostJnlTemplate; Rec."Auto-Post Jnl. Template")
+ {
+ ApplicationArea = All;
+ ToolTip = 'Specifies the general journal template to use for automatically posting payment transactions.';
+ Enabled = Rec."Post Automatically";
+ ShowMandatory = Rec."Post Automatically";
+ }
+ field(AutoPostJnlBatch; Rec."Auto-Post Jnl. Batch")
+ {
+ ApplicationArea = All;
+ ToolTip = 'Specifies the general journal batch to use for automatically posting payment transactions.';
+ Enabled = Rec."Post Automatically";
+ ShowMandatory = Rec."Post Automatically";
+ }
}
}
}
diff --git a/src/Apps/W1/Shopify/App/src/Transactions/Pages/ShpfyTransactions.Page.al b/src/Apps/W1/Shopify/App/src/Transactions/Pages/ShpfyTransactions.Page.al
index 04b48cbf04..f056e31515 100644
--- a/src/Apps/W1/Shopify/App/src/Transactions/Pages/ShpfyTransactions.Page.al
+++ b/src/Apps/W1/Shopify/App/src/Transactions/Pages/ShpfyTransactions.Page.al
@@ -137,6 +137,11 @@ page 30134 "Shpfy Transactions"
ApplicationArea = All;
ToolTip = 'Specifies the Posted Invoice number to which the transaction relates.';
}
+ field("Auto-Post Enabled"; Rec."Auto-Post Enabled")
+ {
+ ApplicationArea = All;
+ ToolTip = 'Specifies whether auto-posting is enabled for the transaction.';
+ }
}
}
}
@@ -194,6 +199,31 @@ page 30134 "Shpfy Transactions"
SuggestPayments.Run();
end;
}
+ action(ShowPostableTransactions)
+ {
+ ApplicationArea = All;
+ Caption = 'Filter Postable Transactions';
+ Image = FilterLines;
+ ToolTip = 'Show transactions that need to be posted. Filters by auto-post enabled, not yet posted, and linked to a posted invoice. Optionally filter by gateway and date range.';
+
+ trigger OnAction()
+ begin
+ FilterPostableTransactions()
+ end;
+ }
+ action(ClearFilter)
+ {
+ ApplicationArea = All;
+ Caption = 'Clear Filter';
+ Image = ClearFilter;
+ ToolTip = 'Remove the postable transactions filter and show all transactions.';
+
+ trigger OnAction()
+ begin
+ Rec.ClearMarks();
+ Rec.MarkedOnly(false);
+ end;
+ }
}
area(Promoted)
{
@@ -210,6 +240,8 @@ page 30134 "Shpfy Transactions"
{
Caption = 'Related';
actionref(CustLedgerEntries_Promoted; CustLedgerEntries) { }
+ actionref(ShowPostableTransactions_Promoted; ShowPostableTransactions) { }
+ actionref(ClearFilter_Promoted; ClearFilter) { }
}
}
}
@@ -232,4 +264,58 @@ page 30134 "Shpfy Transactions"
PresentmentCurrencyVisible := OrderHeader.IsPresentmentCurrencyOrder();
end;
+
+ local procedure FilterPostableTransactions()
+ var
+ PaymentMethodMapping: Record "Shpfy Payment Method Mapping";
+ FilterTransactions: Page "Shpfy Filter Transactions";
+ FilterShopCode: Code[20];
+ FilterCreditCardCompany: Text[50];
+ FilterGateway: Text[30];
+ FilterStartDate: DateTime;
+ FilterEndDate: DateTime;
+ begin
+ if not (FilterTransactions.RunModal() = Action::OK) then
+ exit;
+
+ FilterTransactions.GetParameters(FilterShopCode, FilterGateway, FilterCreditCardCompany, FilterStartDate, FilterEndDate);
+ if (FilterStartDate <> 0DT) or (FilterEndDate <> 0DT) then
+ if FilterEndDate <> 0DT then
+ Rec.SetRange("Created At", FilterStartDate, FilterEndDate)
+ else
+ Rec.SetRange("Created At", FilterStartDate, CreateDateTime(DMY2Date(31, 12, 9999), 0T));
+ Rec.SetRange(Used, false);
+ Rec.SetFilter("Posted Invoice No.", '<>%1', '');
+
+ Rec.ClearMarks();
+ Rec.MarkedOnly(false);
+ if FilterGateway <> '' then
+ MarkPostableTransactions(FilterShopCode, FilterCreditCardCompany, FilterGateway)
+ else begin
+ PaymentMethodMapping.SetRange("Post Automatically", true);
+ if PaymentMethodMapping.FindSet() then
+ repeat
+ MarkPostableTransactions(PaymentMethodMapping."Shop Code", PaymentMethodMapping."Credit Card Company", PaymentMethodMapping.Gateway);
+ until PaymentMethodMapping.Next() = 0;
+ end;
+
+ Rec.MarkedOnly(true);
+ Rec.SetRange(Shop);
+ Rec.SetRange(Gateway);
+ Rec.SetRange("Credit Card Company");
+ Rec.SetRange("Created At");
+ Rec.SetRange(Used);
+ Rec.SetRange("Posted Invoice No.");
+ end;
+
+ local procedure MarkPostableTransactions(FilterShopCode: Code[20]; FilterCreditCardCompany: Text[50]; FilterGateway: Text[30])
+ begin
+ Rec.SetRange(Shop, FilterShopCode);
+ Rec.SetRange(Gateway, FilterGateway);
+ Rec.SetRange("Credit Card Company", FilterCreditCardCompany);
+ if Rec.FindSet() then
+ repeat
+ Rec.Mark(true);
+ until Rec.Next() = 0;
+ end;
}
\ No newline at end of file
diff --git a/src/Apps/W1/Shopify/App/src/Transactions/Reports/ShpfySuggestPayments.Report.al b/src/Apps/W1/Shopify/App/src/Transactions/Reports/ShpfySuggestPayments.Report.al
index 8f95f48835..6b6fd80d28 100644
--- a/src/Apps/W1/Shopify/App/src/Transactions/Reports/ShpfySuggestPayments.Report.al
+++ b/src/Apps/W1/Shopify/App/src/Transactions/Reports/ShpfySuggestPayments.Report.al
@@ -210,6 +210,21 @@ report 30118 "Shpfy Suggest Payments"
IgnorePostedTransactions := NewIgnorePostedTransactions;
end;
+ internal procedure SetOrderTransaction(NewOrderTransaction: Record "Shpfy Order Transaction")
+ begin
+ OrderTransaction := NewOrderTransaction;
+ end;
+
+ internal procedure SetJournalParameters(NewTemplateName: Code[10]; NewBatchName: Code[10]; NewPostingDate: Date)
+ begin
+ GeneralJournalTemplateName := NewTemplateName;
+ GeneralJournalBatchName := NewBatchName;
+ GenJournalLine."Journal Template Name" := NewTemplateName;
+ GenJournalLine."Journal Batch Name" := NewBatchName;
+ PostingDate := NewPostingDate;
+ ValidatePostingDate();
+ end;
+
local procedure ValidatePostingDate()
var
NoSeries: Codeunit "No. Series";
@@ -252,7 +267,7 @@ report 30118 "Shpfy Suggest Payments"
repeat
if SalesInvoiceHeader.Closed then
continue;
- ApplyCustomerLedgerEntries(SalesInvoiceHeader."No.", "Gen. Journal Document Type"::Invoice, AmountToApply, Applied);
+ ApplyCustomerLedgerEntries(OrderTransaction, SalesInvoiceHeader."No.", "Gen. Journal Document Type"::Invoice, AmountToApply, Applied);
until SalesInvoiceHeader.Next() = 0
else begin
DocLinkToDoc.SetRange("Shopify Document Type", DocLinkToDoc."Shopify Document Type"::"Shopify Shop Order");
@@ -263,12 +278,12 @@ report 30118 "Shpfy Suggest Payments"
SalesInvoiceHeader.Get(DocLinkToDoc."Document No.");
if SalesInvoiceHeader.Closed then
continue;
- ApplyCustomerLedgerEntries(SalesInvoiceHeader."No.", "Gen. Journal Document Type"::Invoice, AmountToApply, Applied);
+ ApplyCustomerLedgerEntries(OrderTransaction, SalesInvoiceHeader."No.", "Gen. Journal Document Type"::Invoice, AmountToApply, Applied);
until DocLinkToDoc.Next() = 0;
end;
if Applied and (AmountToApply > 0) then
- CreateSuggestPaymentGLAccount(AmountToApply, true);
+ CreateSuggestPaymentGLAccount(OrderTransaction, AmountToApply, true);
end;
OrderTransaction.Type::Refund:
begin
@@ -283,18 +298,18 @@ report 30118 "Shpfy Suggest Payments"
repeat
if SalesCreditMemoHeader.Paid then
continue;
- ApplyCustomerLedgerEntries(SalesCreditMemoHeader."No.", "Gen. Journal Document Type"::"Credit Memo", AmountToApply, Applied);
+ ApplyCustomerLedgerEntries(OrderTransaction, SalesCreditMemoHeader."No.", "Gen. Journal Document Type"::"Credit Memo", AmountToApply, Applied);
until SalesCreditMemoHeader.Next() = 0;
until RefundHeader.Next() = 0;
if Applied and (AmountToApply > 0) then
- CreateSuggestPaymentGLAccount(AmountToApply, false);
+ CreateSuggestPaymentGLAccount(OrderTransaction, AmountToApply, false);
end;
end;
end;
end;
- local procedure ApplyCustomerLedgerEntries(DocumentNo: Code[20]; DocumentType: Enum "Gen. Journal Document Type"; var AmountToApply: Decimal; var Applied: Boolean)
+ local procedure ApplyCustomerLedgerEntries(OrderTransaction: Record "Shpfy Order Transaction"; DocumentNo: Code[20]; DocumentType: Enum "Gen. Journal Document Type"; var AmountToApply: Decimal; var Applied: Boolean)
var
CustLedgerEntry: Record "Cust. Ledger Entry";
begin
@@ -307,12 +322,12 @@ report 30118 "Shpfy Suggest Payments"
if CustLedgerEntry.FindSet() then begin
Applied := true;
repeat
- CreateSuggestPaymentDocument(CustLedgerEntry, AmountToApply, DocumentType = "Gen. Journal Document Type"::Invoice);
+ CreateSuggestPaymentDocument(CustLedgerEntry, OrderTransaction, AmountToApply, DocumentType = "Gen. Journal Document Type"::Invoice);
until CustLedgerEntry.Next() = 0;
end;
end;
- local procedure CreateSuggestPaymentDocument(var CustLedgerEntry: Record "Cust. Ledger Entry"; var AmountToApply: Decimal; IsInvoice: Boolean)
+ local procedure CreateSuggestPaymentDocument(var CustLedgerEntry: Record "Cust. Ledger Entry"; OrderTransaction: Record "Shpfy Order Transaction"; var AmountToApply: Decimal; IsInvoice: Boolean)
begin
TempSuggestPayment.Init();
EntryNo += 1;
@@ -346,7 +361,7 @@ report 30118 "Shpfy Suggest Payments"
TempSuggestPayment.Insert();
end;
- local procedure CreateSuggestPaymentGLAccount(AmountToApply: Decimal; IsInvoice: Boolean)
+ local procedure CreateSuggestPaymentGLAccount(OrderTransaction: Record "Shpfy Order Transaction"; AmountToApply: Decimal; IsInvoice: Boolean)
begin
TempSuggestPayment.Init();
EntryNo += 1;
@@ -375,6 +390,8 @@ report 30118 "Shpfy Suggest Payments"
if GenJournalLine.FindLast() then
LastLineNo := GenJournalLine."Line No.";
+ RemoveGenJournalLines(TempSuggestPayment."Shpfy Transaction Id");
+
if OrderNoInDescription then
TempSuggestPayment.SetAutoCalcFields("Shpfy Order No.");
if TempSuggestPayment.FindSet() then
@@ -426,6 +443,13 @@ report 30118 "Shpfy Suggest Payments"
until TempSuggestPayment.Next() = 0;
end;
+ local procedure RemoveGenJournalLines(ShopifyTransactionId: BigInteger)
+ begin
+ GenJournalLine.SetRange("Shpfy Transaction Id", ShopifyTransactionId);
+ if not GenJournalLine.IsEmpty() then
+ GenJournalLine.DeleteAll(true);
+ end;
+
local procedure SetGenJournallLineDimension(CustomerLedgerEntryDimensionSetId: Integer)
var
DimensionManagement: Codeunit DimensionManagement;
diff --git a/src/Apps/W1/Shopify/App/src/Transactions/Table Extensions/ShpfyGenJournalLine.TableExt.al b/src/Apps/W1/Shopify/App/src/Transactions/Table Extensions/ShpfyGenJournalLine.TableExt.al
index 48bcbacdb0..76865a958e 100644
--- a/src/Apps/W1/Shopify/App/src/Transactions/Table Extensions/ShpfyGenJournalLine.TableExt.al
+++ b/src/Apps/W1/Shopify/App/src/Transactions/Table Extensions/ShpfyGenJournalLine.TableExt.al
@@ -17,5 +17,10 @@ tableextension 30202 "Shpfy Gen. Journal Line" extends "Gen. Journal Line"
DataClassification = SystemMetadata;
Editable = false;
}
+ field(30101; "Automatically Posted"; Boolean)
+ {
+ Caption = 'Automatically Posted';
+ DataClassification = SystemMetadata;
+ }
}
}
\ No newline at end of file
diff --git a/src/Apps/W1/Shopify/App/src/Transactions/Tables/ShpfyOrderTransaction.Table.al b/src/Apps/W1/Shopify/App/src/Transactions/Tables/ShpfyOrderTransaction.Table.al
index 809a064dc4..a3a702ac51 100644
--- a/src/Apps/W1/Shopify/App/src/Transactions/Tables/ShpfyOrderTransaction.Table.al
+++ b/src/Apps/W1/Shopify/App/src/Transactions/Tables/ShpfyOrderTransaction.Table.al
@@ -271,6 +271,12 @@ table 30133 "Shpfy Order Transaction"
Caption = 'Shop Code';
TableRelation = "Shpfy Shop";
}
+ field(100; "Auto-Post Enabled"; Boolean)
+ {
+ Caption = 'Auto-Post Enabled';
+ FieldClass = FlowField;
+ CalcFormula = lookup("Shpfy Payment Method Mapping"."Post Automatically" where("Shop Code" = field("Shop"), Gateway = field(Gateway), "Credit Card Company" = field("Credit Card Company")));
+ }
}
keys
diff --git a/src/Apps/W1/Shopify/App/src/Transactions/Tables/ShpfyPaymentMethodMapping.Table.al b/src/Apps/W1/Shopify/App/src/Transactions/Tables/ShpfyPaymentMethodMapping.Table.al
index e1ee2fb335..c57b7f5e7d 100644
--- a/src/Apps/W1/Shopify/App/src/Transactions/Tables/ShpfyPaymentMethodMapping.Table.al
+++ b/src/Apps/W1/Shopify/App/src/Transactions/Tables/ShpfyPaymentMethodMapping.Table.al
@@ -6,6 +6,7 @@
namespace Microsoft.Integration.Shopify;
using Microsoft.Bank.BankAccount;
+using Microsoft.Finance.GeneralLedger.Journal;
///
/// Table Shpfy Payment Method Mapping (ID 30134).
@@ -14,6 +15,8 @@ table 30134 "Shpfy Payment Method Mapping"
{
Access = Internal;
Caption = 'Shopify Payment Method';
+ DrillDownPageID = "Shpfy Payment Methods Mapping";
+ LookupPageID = "Shpfy Payment Methods Mapping";
DataClassification = CustomerContent;
fields
@@ -59,6 +62,33 @@ table 30134 "Shpfy Payment Method Mapping"
DataClassification = SystemMetadata;
Editable = false;
}
+ field(7; "Post Automatically"; Boolean)
+ {
+ Caption = 'Post Automatically';
+ DataClassification = CustomerContent;
+ }
+ field(8; "Auto-Post Jnl. Template"; Code[10])
+ {
+ Caption = 'Auto-Post Journal Template';
+ DataClassification = CustomerContent;
+ TableRelation = "Gen. Journal Template" where(Type = const("Cash Receipts"));
+ }
+ field(9; "Auto-Post Jnl. Batch"; Code[10])
+ {
+ Caption = 'Auto-Post Journal Batch';
+ DataClassification = CustomerContent;
+ TableRelation = "Gen. Journal Batch".Name where("Journal Template Name" = field("Auto-Post Jnl. Template"));
+
+ trigger OnValidate()
+ var
+ GenJournalBatch: Record "Gen. Journal Batch";
+ begin
+ if "Auto-Post Jnl. Batch" <> '' then begin
+ GenJournalBatch.Get("Auto-Post Jnl. Template", "Auto-Post Jnl. Batch");
+ GenJournalBatch.TestField("Bal. Account No.");
+ end;
+ end;
+ }
}
keys
{
diff --git a/src/Apps/W1/Shopify/Test/Payments/ShpfyAutoPostTransTest.Codeunit.al b/src/Apps/W1/Shopify/Test/Payments/ShpfyAutoPostTransTest.Codeunit.al
new file mode 100644
index 0000000000..4688231372
--- /dev/null
+++ b/src/Apps/W1/Shopify/Test/Payments/ShpfyAutoPostTransTest.Codeunit.al
@@ -0,0 +1,503 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace Microsoft.Integration.Shopify.Test;
+
+using Microsoft.Finance.GeneralLedger.Account;
+using Microsoft.Finance.GeneralLedger.Journal;
+using Microsoft.Finance.GeneralLedger.Setup;
+using Microsoft.Finance.VAT.Setup;
+using Microsoft.Foundation.Enums;
+using Microsoft.Foundation.NoSeries;
+using Microsoft.Integration.Shopify;
+using Microsoft.Inventory.Item;
+using Microsoft.Sales.Customer;
+using Microsoft.Sales.Document;
+using Microsoft.Sales.History;
+using Microsoft.Sales.Receivables;
+using System.TestLibraries.Utilities;
+
+///
+/// Codeunit Shpfy Auto Post Transaction Test (ID 139614).
+///
+codeunit 139614 "Shpfy Auto Post Trans. Test"
+{
+ Subtype = Test;
+ TestPermissions = Disabled;
+
+ var
+ Customer: Record Customer;
+ Item: Record Item;
+ Shop: Record "Shpfy Shop";
+ PaymentMethodMapping: Record "Shpfy Payment Method Mapping";
+ LibraryAssert: Codeunit "Library Assert";
+ LibraryRandom: Codeunit "Library - Random";
+ LibrarySales: Codeunit "Library - Sales";
+ IsInitialized: Boolean;
+
+ [Test]
+ procedure UnitTestAutoPostJnlBatchValidateWithBalAccountNo()
+ var
+ ShpfyPaymentMethodMapping: Record "Shpfy Payment Method Mapping";
+ GenJournalBatch: Record "Gen. Journal Batch";
+ begin
+ // [SCENARIO] Auto-Post Jnl. Batch field validates successfully when journal batch has a balancing account number
+
+ // [GIVEN] A Gen. Journal Batch with a balancing account number
+ CreateJournalBatch(GenJournalBatch);
+ ShpfyPaymentMethodMapping."Auto-Post Jnl. Template" := GenJournalBatch."Journal Template Name";
+
+ // [WHEN] Auto-Post Jnl. Batch is validated
+ ShpfyPaymentMethodMapping.Validate("Auto-Post Jnl. Batch", GenJournalBatch.Name);
+
+ // [THEN] Validation passes without error
+ LibraryAssert.AreEqual(GenJournalBatch.Name, ShpfyPaymentMethodMapping."Auto-Post Jnl. Batch", 'Auto-Post Jnl. Batch should be set');
+ end;
+
+ [Test]
+ procedure UnitTestAutoPostJnlBatchValidateWithoutBalAccountNo()
+ var
+ ShpfyPaymentMethodMapping: Record "Shpfy Payment Method Mapping";
+ GenJournalBatch: Record "Gen. Journal Batch";
+ begin
+ // [SCENARIO] Auto-Post Jnl. Batch field validation fails when journal batch does not have a balancing account number
+
+ // [GIVEN] A Gen. Journal Batch without a balancing account number
+ CreateJournalBatch(GenJournalBatch);
+ GenJournalBatch."Bal. Account No." := '';
+ GenJournalBatch.Modify();
+ ShpfyPaymentMethodMapping."Auto-Post Jnl. Template" := GenJournalBatch."Journal Template Name";
+
+ // [WHEN] Auto-Post Jnl. Batch is validated
+ // [THEN] Validation fails with error
+ asserterror ShpfyPaymentMethodMapping.Validate("Auto-Post Jnl. Batch", GenJournalBatch.Name);
+ end;
+
+ [Test]
+ procedure UnitTestAutoPostJnlBatchValidateWithEmptyValue()
+ var
+ ShpfyPaymentMethodMapping: Record "Shpfy Payment Method Mapping";
+ begin
+ // [SCENARIO] Auto-Post Jnl. Batch field can be set to empty without validation error
+
+ // [WHEN] Auto-Post Jnl. Batch is set to empty
+ ShpfyPaymentMethodMapping.Validate("Auto-Post Jnl. Batch", '');
+
+ // [THEN] Validation passes without error
+ LibraryAssert.AreEqual('', ShpfyPaymentMethodMapping."Auto-Post Jnl. Batch", 'Auto-Post Jnl. Batch should be empty');
+ end;
+
+ [Test]
+ procedure UnitTestPostSalesOrderWithAutoPostTransaction()
+ var
+ SalesHeader: Record "Sales Header";
+ CustLedgerEntry: Record "Cust. Ledger Entry";
+ OrderId: BigInteger;
+ TransactionId: BigInteger;
+ begin
+ // [SCENARIO] When a sales order with Shopify Order Id is posted and Post Automatically is true, transaction is auto-posted
+
+ // [GIVEN] Initialized test environment
+ Initialize();
+
+ // [GIVEN] A Shopify order with transaction
+ OrderId := LibraryRandom.RandIntInRange(1000000, 1999999);
+ TransactionId := LibraryRandom.RandIntInRange(1000000, 1999999);
+ CreateShopifyOrder(OrderId);
+ CreateOrderTransaction(TransactionId, OrderId, 0, PaymentMethodMapping.Gateway, Enum::"Shpfy Transaction Type"::Sale, Item."Unit Price");
+
+ // [GIVEN] Payment method mapping with auto-post enabled
+ EnablePaymentMethodMappingAutoPost(true);
+
+ // [GIVEN] A sales order with Shopify Order Id
+ CreateSalesOrder(SalesHeader, OrderId);
+
+ // [WHEN] The sales order is posted
+ LibrarySales.PostSalesDocument(SalesHeader, true, true);
+
+ // [THEN] A Cust. Ledger Entry is created
+ CustLedgerEntry.SetRange("Shpfy Transaction Id", TransactionId);
+ LibraryAssert.IsTrue(not CustLedgerEntry.IsEmpty(), 'Cust. Ledger Entry should be created for the auto-posted transaction');
+ end;
+
+ [Test]
+ procedure UnitTestPostSalesOrderWithoutAutoPostTransaction()
+ var
+ SalesHeader: Record "Sales Header";
+ CustLedgerEntry: Record "Cust. Ledger Entry";
+ OrderId: BigInteger;
+ TransactionId: BigInteger;
+ begin
+ // [SCENARIO] When a sales order with Shopify Order Id is posted and Post Automatically is false, transaction is not auto-posted
+
+ // [GIVEN] Initialized test environment
+ Initialize();
+
+ // [GIVEN] A Shopify order with transaction
+ OrderId := LibraryRandom.RandIntInRange(2000000, 2999999);
+ TransactionId := LibraryRandom.RandIntInRange(2000000, 2999999);
+ CreateShopifyOrder(OrderId);
+ CreateOrderTransaction(TransactionId, OrderId, 0, PaymentMethodMapping.Gateway, Enum::"Shpfy Transaction Type"::Sale, Item."Unit Price");
+
+ // [GIVEN] Payment method mapping with auto-post disabled
+ EnablePaymentMethodMappingAutoPost(false);
+
+ // [GIVEN] A sales order with Shopify Order Id
+ CreateSalesOrder(SalesHeader, OrderId);
+
+ // [WHEN] The sales order is posted
+ LibrarySales.PostSalesDocument(SalesHeader, true, true);
+
+ // [THEN] A Cust. Ledger Entry is not created
+ CustLedgerEntry.SetRange("Shpfy Transaction Id", TransactionId);
+ LibraryAssert.IsTrue(CustLedgerEntry.IsEmpty(), 'Cust. Ledger Entry should not be created for the non-auto-posted transaction');
+ end;
+
+ [Test]
+ procedure UnitTestPostSalesOrderWithAutoPostMultipleTransaction()
+ var
+ SalesHeader: Record "Sales Header";
+ CustLedgerEntry: Record "Cust. Ledger Entry";
+ TransactionId1: BigInteger;
+ TransactionId2: BigInteger;
+ OrderId: BigInteger;
+ begin
+ // [SCENARIO] When a sales order with Shopify Order Id is posted and Post Automatically is true, multiple transactions are auto-posted
+
+ // [GIVEN] Initialized test environment
+ Initialize();
+
+ // [GIVEN] A Shopify order with multiple transactions
+ OrderId := LibraryRandom.RandIntInRange(3000000, 3999999);
+ CreateShopifyOrder(OrderId);
+ TransactionId1 := LibraryRandom.RandIntInRange(3000000, 3499999);
+ TransactionId2 := LibraryRandom.RandIntInRange(3500000, 3999999);
+ CreateOrderTransaction(TransactionId1, OrderId, 0, PaymentMethodMapping.Gateway, Enum::"Shpfy Transaction Type"::Sale, Item."Unit Price" / 2);
+ CreateOrderTransaction(TransactionId2, OrderId, 0, PaymentMethodMapping.Gateway, Enum::"Shpfy Transaction Type"::Sale, Item."Unit Price" / 2);
+
+ // [GIVEN] Payment method mapping with auto-post enabled
+ EnablePaymentMethodMappingAutoPost(true);
+
+ // [GIVEN] A sales order with Shopify Order Id
+ CreateSalesOrder(SalesHeader, OrderId);
+
+ // [WHEN] The sales order is posted
+ LibrarySales.PostSalesDocument(SalesHeader, true, true);
+
+ // [THEN] A Cust. Ledger Entry is created
+ CustLedgerEntry.SetRange("Shpfy Transaction Id", TransactionId1);
+ LibraryAssert.IsTrue(not CustLedgerEntry.IsEmpty(), 'Cust. Ledger Entry should be created for the auto-posted transaction');
+ CustLedgerEntry.SetRange("Shpfy Transaction Id", TransactionId2);
+ LibraryAssert.IsTrue(not CustLedgerEntry.IsEmpty(), 'Cust. Ledger Entry should be created for the auto-posted transaction');
+ end;
+
+ [Test]
+ procedure UnitTestPostSalesOrderWithMultipleTransaction()
+ var
+ SalesHeader: Record "Sales Header";
+ CustLedgerEntry: Record "Cust. Ledger Entry";
+ TransactionId1: BigInteger;
+ TransactionId2: BigInteger;
+ OrderId: BigInteger;
+ begin
+ // [SCENARIO] When a sales order with Shopify Order Id is posted and Post Automatically is true, only transactions linked to auto post Payment Method Mapping are auto-posted
+
+ // [GIVEN] Initialized test environment
+ Initialize();
+
+ // [GIVEN] A Shopify order
+ OrderId := LibraryRandom.RandIntInRange(4000000, 4999999);
+ CreateShopifyOrder(OrderId);
+
+ // [GIVEN] Payment method mapping with auto-post enabled
+ EnablePaymentMethodMappingAutoPost(true);
+
+ // [GIVEN] Transaction linked to auto post Payment Method Mapping
+ TransactionId1 := LibraryRandom.RandIntInRange(4000000, 4499999);
+ CreateOrderTransaction(TransactionId1, OrderId, 0, PaymentMethodMapping.Gateway, Enum::"Shpfy Transaction Type"::Sale, Item."Unit Price" / 2);
+
+ // [GIVEN] Transaction not linked to auto post Payment Method Mapping
+ TransactionId2 := LibraryRandom.RandIntInRange(4500000, 4999999);
+ CreateOrderTransaction(TransactionId2, OrderId, 0, 'auto post disabled', Enum::"Shpfy Transaction Type"::Sale, Item."Unit Price" / 2);
+
+ // [GIVEN] A sales order with Shopify Order Id
+ CreateSalesOrder(SalesHeader, OrderId);
+
+ // [WHEN] The sales order is posted
+ LibrarySales.PostSalesDocument(SalesHeader, true, true);
+
+ // [THEN] A Cust. Ledger Entry is created
+ CustLedgerEntry.SetRange("Shpfy Transaction Id", TransactionId1);
+ LibraryAssert.IsTrue(not CustLedgerEntry.IsEmpty(), 'Cust. Ledger Entry should be created for the auto-posted transaction');
+ CustLedgerEntry.SetRange("Shpfy Transaction Id", TransactionId2);
+ LibraryAssert.IsTrue(CustLedgerEntry.IsEmpty(), 'Cust. Ledger Entry should not be created for the non-auto-posted transaction');
+ end;
+
+ [Test]
+ procedure UnitTestPostCreditMemoWithAutoPostTransaction()
+ var
+ SalesHeader: Record "Sales Header";
+ CustLedgerEntry: Record "Cust. Ledger Entry";
+ TransactionId: BigInteger;
+ RefundId: BigInteger;
+ OrderId: BigInteger;
+ begin
+ // [SCENARIO] When a credit memo with Shopify Refund Id is posted and Post Automatically is true, refund transaction is auto-posted
+
+ // [GIVEN] Initialized test environment
+ Initialize();
+
+ // [GIVEN] A refund with transaction
+ RefundId := LibraryRandom.RandIntInRange(5000000, 5999999);
+ OrderId := LibraryRandom.RandIntInRange(5000000, 5999999);
+ CreateShopifyOrder(OrderId);
+ CreateRefund(RefundId, OrderId);
+ TransactionId := LibraryRandom.RandIntInRange(5000000, 5999999);
+ CreateOrderTransaction(TransactionId, OrderId, RefundId, PaymentMethodMapping.Gateway, Enum::"Shpfy Transaction Type"::Refund, Item."Unit Price");
+
+ // [GIVEN] Payment method mapping with auto-post enabled
+ EnablePaymentMethodMappingAutoPost(true);
+
+ // [GIVEN] A sales credit memo with Shopify Refund Id
+ CreateCreditMemo(SalesHeader, RefundId);
+
+ // [WHEN] The credit memo is posted
+ LibrarySales.PostSalesDocument(SalesHeader, true, true);
+
+ // [THEN] A Cust. Ledger Entry is created
+ CustLedgerEntry.SetRange("Shpfy Transaction Id", TransactionId);
+ LibraryAssert.IsTrue(not CustLedgerEntry.IsEmpty(), 'Cust. Ledger Entry should be created for the auto-posted refund transaction');
+ end;
+
+ [Test]
+ procedure UnitTestPostSalesOrderWithUnsuccessfulTransactionPost()
+ var
+ SalesHeader: Record "Sales Header";
+ SalesInvoiceHeader: Record "Sales Invoice Header";
+ CustLedgerEntry: Record "Cust. Ledger Entry";
+ OrderId: BigInteger;
+ TransactionId: BigInteger;
+ begin
+ // [SCENARIO] When a sales order with Shopify Order Id is posted and Post Automatically is true, transaction post is unsuccessful, but sales order posting is completed
+
+ // [GIVEN] Initialized test environment
+ Initialize();
+
+ // [GIVEN] A Shopify order with transaction
+ OrderId := LibraryRandom.RandIntInRange(6000000, 6999999);
+ TransactionId := LibraryRandom.RandIntInRange(6000000, 6999999);
+ CreateShopifyOrder(OrderId);
+ CreateOrderTransaction(TransactionId, OrderId, 0, PaymentMethodMapping.Gateway, Enum::"Shpfy Transaction Type"::Sale, Item."Unit Price");
+
+ // [GIVEN] Payment method mapping with auto-post enabled
+ EnablePaymentMethodMappingAutoPost(true);
+
+ // [GIVEN] A sales order with Shopify Order Id
+ CreateSalesOrder(SalesHeader, OrderId);
+
+ // [GIVEN] Transaction auto post No. Series is closed
+ OpenNoSeriesLine(false);
+
+ // [WHEN] The sales order is posted
+ asserterror LibrarySales.PostSalesDocument(SalesHeader, true, true);
+
+ // [THEN] Sales order posting is completed
+ SalesInvoiceHeader.SetRange("Shpfy Order Id", OrderId);
+ LibraryAssert.IsTrue(not SalesInvoiceHeader.IsEmpty(), 'Posted sales invoice should exist');
+
+ // [THEN] A Cust. Ledger Entry is not created
+ CustLedgerEntry.SetRange("Shpfy Transaction Id", TransactionId);
+ LibraryAssert.IsTrue(CustLedgerEntry.IsEmpty(), 'Cust. Ledger Entry should not be created for the auto-posted transaction');
+
+ OpenNoSeriesLine(true);
+ end;
+
+ local procedure Initialize()
+ var
+ LibraryERMCountryData: Codeunit "Library - ERM Country Data";
+ CommunicationMgt: Codeunit "Shpfy Communication Mgt.";
+ begin
+ if IsInitialized then
+ exit;
+
+ Codeunit.Run(Codeunit::"Shpfy Initialize Test");
+
+ LibraryERMCountryData.CreateVATData();
+ LibraryERMCountryData.UpdateGeneralPostingSetup();
+ CreateItem();
+ LibrarySales.CreateCustomer(Customer);
+
+ Shop := CommunicationMgt.GetShopRecord();
+
+ CreatePaymentMethodMapping();
+
+ DisablePostWithJobQueue();
+
+ IsInitialized := true;
+ end;
+
+ local procedure DisablePostWithJobQueue()
+ var
+ GeneralLedgerSetup: Record "General Ledger Setup";
+ begin
+ GeneralLedgerSetup.Get();
+ GeneralLedgerSetup."Post with Job Queue" := false;
+ GeneralLedgerSetup.Modify();
+ end;
+
+ local procedure CreateItem()
+ var
+ LibraryInventory: Codeunit "Library - Inventory";
+ Amount: Decimal;
+ begin
+ Amount := LibraryRandom.RandIntInRange(10000, 99999);
+ LibraryInventory.CreateItem(Item);
+ Item.Validate("Unit Price", Amount);
+ Item.Validate("Last Direct Cost", Amount);
+ Item.Modify(true);
+ end;
+
+ local procedure CreateShopifyOrder(OrderId: BigInteger)
+ var
+ ShpfyOrderHeader: Record "Shpfy Order Header";
+ begin
+ ShpfyOrderHeader.Init();
+ ShpfyOrderHeader."Shopify Order Id" := OrderId;
+ ShpfyOrderHeader.Processed := true;
+ ShpfyOrderHeader.Insert();
+ end;
+
+ local procedure CreateOrderTransaction(TransactionId: BigInteger; OrderId: BigInteger; RefundId: BigInteger; Gateway: Text[30]; TransactionType: Enum "Shpfy Transaction Type"; Amount: Decimal)
+ var
+ OrderTransaction: Record "Shpfy Order Transaction";
+ begin
+ OrderTransaction.Init();
+ OrderTransaction."Shopify Transaction Id" := TransactionId;
+ OrderTransaction."Shopify Order Id" := OrderId;
+ OrderTransaction."Refund Id" := RefundId;
+ OrderTransaction.Shop := Shop.Code;
+ OrderTransaction.Gateway := Gateway;
+ OrderTransaction.Type := TransactionType;
+ OrderTransaction.Status := OrderTransaction.Status::Success;
+ OrderTransaction.Amount := Amount;
+ OrderTransaction.Used := false;
+ OrderTransaction.Insert();
+ end;
+
+ local procedure CreateSalesOrder(var SalesHeader: Record "Sales Header"; OrderId: BigInteger)
+ var
+ SalesLine: Record "Sales Line";
+ begin
+ LibrarySales.CreateSalesHeader(SalesHeader, SalesHeader."Document Type"::Invoice, Customer."No.");
+ SalesHeader."Shpfy Order Id" := OrderId;
+ SalesHeader.Modify();
+ LibrarySales.CreateSalesLine(SalesLine, SalesHeader, SalesLine.Type::Item, Item."No.", 1);
+ end;
+
+ local procedure CreateCreditMemo(var SalesHeader: Record "Sales Header"; RefundId: BigInteger)
+ var
+ SalesLine: Record "Sales Line";
+ begin
+ LibrarySales.CreateSalesHeader(SalesHeader, SalesHeader."Document Type"::"Credit Memo", Customer."No.");
+ SalesHeader."Shpfy Refund Id" := RefundId;
+ SalesHeader.Modify();
+ LibrarySales.CreateSalesLine(SalesLine, SalesHeader, SalesLine.Type::Item, Item."No.", 1);
+ end;
+
+ local procedure CreateRefund(RefundId: BigInteger; OrderId: BigInteger)
+ var
+ RefundHeader: Record "Shpfy Refund Header";
+ begin
+ RefundHeader.Init();
+ RefundHeader."Refund Id" := RefundId;
+ RefundHeader."Order Id" := OrderId;
+ RefundHeader.Insert();
+ end;
+
+ local procedure EnablePaymentMethodMappingAutoPost(AutoPost: Boolean)
+ begin
+ PaymentMethodMapping."Post Automatically" := AutoPost;
+ PaymentMethodMapping.Modify();
+ end;
+
+ local procedure CreatePaymentMethodMapping()
+ var
+ GenJournalBatch: Record "Gen. Journal Batch";
+ begin
+ PaymentMethodMapping.Init();
+ PaymentMethodMapping."Shop Code" := Shop.Code;
+ PaymentMethodMapping.Gateway := CopyStr(LibraryRandom.RandText(30), 1, MaxStrLen(PaymentMethodMapping.Gateway));
+ PaymentMethodMapping."Post Automatically" := true;
+ CreateJournalBatch(GenJournalBatch);
+ PaymentMethodMapping."Auto-Post Jnl. Template" := GenJournalBatch."Journal Template Name";
+ PaymentMethodMapping."Auto-Post Jnl. Batch" := GenJournalBatch.Name;
+ PaymentMethodMapping.Insert();
+ end;
+
+ local procedure CreateJournalBatch(var GenJournalBatch: Record "Gen. Journal Batch")
+ var
+ GenJournalTemplate: Record "Gen. Journal Template";
+ begin
+ GenJournalTemplate.Name := CopyStr(LibraryRandom.RandText(10), 1, MaxStrLen(GenJournalTemplate.Name));
+ GenJournalTemplate.Type := GenJournalTemplate.Type::"Cash Receipts";
+ GenJournalTemplate.Insert();
+
+ GenJournalBatch."Journal Template Name" := GenJournalTemplate.Name;
+ GenJournalBatch.Name := CopyStr(LibraryRandom.RandText(10), 1, MaxStrLen(GenJournalBatch.Name));
+ GenJournalBatch."Bal. Account Type" := GenJournalBatch."Bal. Account Type"::"G/L Account";
+ GenJournalBatch."Bal. Account No." := CreateGLAccount();
+ GenJournalBatch."No. Series" := CopyStr(LibraryRandom.RandText(20), 1, MaxStrLen(GenJournalBatch."No. Series"));
+ CreateNoSeries(GenJournalBatch."No. Series");
+ GenJournalBatch.Insert();
+ end;
+
+ local procedure CreateGLAccount(): Code[20]
+ var
+ GLAccount: Record "G/L Account";
+ VATPostingSetup: Record "VAT Posting Setup";
+ LibraryERM: Codeunit "Library - ERM";
+ ShpfyInitializeTest: Codeunit "Shpfy Initialize Test";
+ begin
+ LibraryERM.CreateVATPostingSetupWithAccounts(VATPostingSetup, VATPostingSetup."VAT Calculation Type"::"Normal VAT", LibraryRandom.RandDecInDecimalRange(10, 25, 0));
+ GLAccount.Get(LibraryERM.CreateGLAccountWithVATPostingSetup(VATPostingSetup, Enum::"General Posting Type"::Sale));
+ GLAccount."Direct Posting" := true;
+
+ ShpfyInitializeTest.CreateVATPostingSetup(Shop."VAT Bus. Posting Group", GLAccount."VAT Prod. Posting Group");
+
+ GLAccount.Modify(false);
+ exit(GLAccount."No.");
+ end;
+
+ local procedure CreateNoSeries(Code: Code[20])
+ var
+ NoSeries: Record "No. Series";
+ NoSeriesLine: Record "No. Series Line";
+ begin
+ if not NoSeries.Get(Code) then begin
+ NoSeries.Code := Code;
+ NoSeries."Default Nos." := true;
+ NoSeries.Insert();
+ NoSeriesLine."Series Code" := Code;
+ NoSeriesLine."Starting No." := Format(LibraryRandom.RandIntInRange(10000, 39999));
+ NoSeriesLine."Increment-by No." := 1;
+ NoSeriesLine."Ending No." := Format(LibraryRandom.RandIntInRange(50000, 99999));
+ NoSeriesLine.Open := true;
+ NoSeriesLine.Insert();
+ end;
+ end;
+
+ local procedure OpenNoSeriesLine(Open: Boolean)
+ var
+ GenJournalBatch: Record "Gen. Journal Batch";
+ NoSeriesLine: Record "No. Series Line";
+ begin
+ GenJournalBatch.Get(PaymentMethodMapping."Auto-Post Jnl. Template", PaymentMethodMapping."Auto-Post Jnl. Batch");
+ NoSeriesLine.SetRange("Series Code", GenJournalBatch."No. Series");
+ if NoSeriesLine.FindFirst() then begin
+ NoSeriesLine.Open := Open;
+ NoSeriesLine.Modify();
+ end;
+ end;
+}