Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Field Service Integration] Additional synchronization entities #27250

Open
wants to merge 51 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
48b9d78
added: additional field service integration type
plakna Aug 27, 2024
66d9f9c
added: navigation actions for invalid no series message
plakna Aug 28, 2024
0f64dc7
added: missing setup checks
plakna Aug 28, 2024
395245f
added: mandatory flag (depends on setup)
plakna Aug 28, 2024
83eacc4
added: service order sync trigger - via service (item) line
plakna Aug 29, 2024
865ee28
added: auto archive on delete service (item) line
plakna Aug 29, 2024
01b63fa
added: sync without service item no.
plakna Aug 29, 2024
d9e602f
added: support of archived services orders (update posted quantities)
plakna Sep 4, 2024
52deb44
added: support of job plan line reversal
plakna Sep 5, 2024
e30acae
added: default value for integrate to service (service order type)
plakna Sep 5, 2024
24baad5
added: bookable resource bookings sync
plakna Sep 5, 2024
05d02fc
added: use max value and resync estimated qty if not used only
plakna Sep 6, 2024
2da075d
added: coupled to field service flag
plakna Sep 6, 2024
7e759c2
added: auto enable service order archive
plakna Sep 6, 2024
032b137
modified: editable of setup fields (wizard and setup card)
plakna Sep 9, 2024
c4bd193
added: posted service invoice api
plakna Sep 10, 2024
29fca4e
added: bidirectional service item description sync
plakna Sep 11, 2024
38d8543
fixed: datetime to date conversation issue
plakna Sep 11, 2024
208d734
added: quantity/duration shipped sync
plakna Sep 11, 2024
fa4fe56
fixed: sync of bookable resource bookings
plakna Sep 11, 2024
19619d9
fixed: missing modification trigger
plakna Sep 11, 2024
4c3cde7
fixed: sync of bookable resource bookings
plakna Sep 11, 2024
52026af
Merge branch 'main' into main
plakna Sep 16, 2024
6930b16
fixed: object no conflicts
plakna Sep 16, 2024
adaf4f2
added: crm redirect event subscriber
plakna Sep 17, 2024
8756702
added: unit tests
plakna Sep 17, 2024
6b2aacd
added: only sync work order product/service if IntegrateToService=false
plakna Sep 12, 2024
bc8ad1e
added: company id
plakna Sep 26, 2024
8e32a89
fixed: typo
plakna Oct 1, 2024
406e185
added: redirect to archive for "show in bc button"
plakna Oct 1, 2024
df1be68
fixed: explicit call of service item sync
plakna Oct 3, 2024
ce80929
fixed: optional location code
plakna Oct 3, 2024
220e074
removed: product id on work order service (only necessaryfor product)
plakna Oct 3, 2024
dd91a3c
added: separate service item line for bookings
plakna Oct 3, 2024
c5fd58e
added: skip reimport for sales (item) lines
plakna Oct 3, 2024
458d48e
added: status sync
plakna Oct 4, 2024
480f543
modified: object id of archived service order job
plakna Oct 4, 2024
9f56808
removed: unnecessary namespace usings
plakna Oct 7, 2024
5b37b92
fixed: product id label
plakna Oct 16, 2024
8853f1a
fixed: missing objects in permissionset files
plakna Oct 16, 2024
d1c72e0
fixed: sync of service item line / work order incident
plakna Oct 16, 2024
26dec3f
added: filled service item line no test
plakna Oct 20, 2024
03e5828
added: reset of qty to ship/invoice/consume fields
plakna Oct 20, 2024
575119a
added: auto sync of uncoupled work orders (on open page)
plakna Oct 21, 2024
3a11be6
removed: resync of pending state
plakna Oct 21, 2024
d1bc26c
added: skip work orders without incidents
plakna Oct 21, 2024
b957eec
added: support of min qty
plakna Oct 24, 2024
7294528
updated: unit tests
plakna Oct 24, 2024
b621466
added: explicit validation of customer related fields
plakna Oct 24, 2024
8f18274
Merge branch 'main' into main
plakna Nov 6, 2024
d603527
added: paid status in posted service invoice api
plakna Nov 6, 2024
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
9 changes: 8 additions & 1 deletion Apps/W1/FieldServiceIntegration/app/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@
"contextSensitiveHelpUrl": "https://learn.microsoft.com/dynamics365/business-central/",
"url": "https://go.microsoft.com/fwlink/?LinkId=724011",
"logo": "ExtensionLogo.png",
"dependencies": [],
"dependencies": [
{
"id": "10cb69d9-bc8a-4d27-970a-9e110e9db2a5",
"name": "_Exclude_APIV2_",
"publisher": "Microsoft",
"version": "25.0.0.0"
}
],
"internalsVisibleTo": [
{
"id": "41b3ab6e-3f20-47c7-a67f-feccc4d58a55",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
// ------------------------------------------------------------------------------------------------
// 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.DynamicsFieldService;

using Microsoft.Integration.Dataverse;
using Microsoft.Integration.SyncEngine;
using Microsoft.Service.Document;
using System.Threading;
using Microsoft.Service.Archive;

codeunit 6618 "FS Archived Service Orders Job"
{
TableNo = "Job Queue Entry";

trigger OnRun()
begin
UpdateOrders(Rec.GetLastLogEntryNo());
end;

var
ArchivedOrdersUpdatedMsg: Label 'Archived service orders have been synchronized.';

local procedure UpdateOrders(JobLogEntryNo: Integer)
var
FSConnectionSetup: Record "FS Connection Setup";
begin
if not FSConnectionSetup.IsEnabled() then
exit;

Codeunit.Run(Codeunit::"CRM Integration Management");
UpdateArchivedOrders(JobLogEntryNo);
end;

local procedure UpdateArchivedOrders(JobLogEntryNo: Integer)
var
CRMIntegrationRecord: Record "CRM Integration Record";
CRMIntegrationRecord2: Record "CRM Integration Record";
FSWorkOrder: Record "FS Work Order";
IntegrationTableSynch: Codeunit "Integration Table Synch.";
SynchActionType: Option "None",Insert,Modify,ForceModify,IgnoreUnchanged,Fail,Skip,Delete;
ModifyCounter: Integer;
begin
IntegrationTableSynch.BeginIntegrationSynchJobLoging(TableConnectionType::CRM, Codeunit::"FS Archived Service Orders Job", JobLogEntryNo, Database::"Service Header");

CRMIntegrationRecord.SetRange("Archived Service Order", true);
CRMIntegrationRecord.SetRange("Archived Service Order Updated", false);
if CRMIntegrationRecord.FindSet() then
repeat
if FSWorkOrder.Get(CRMIntegrationRecord."CRM ID") then
if UpdateFromServiceHeader(FSWorkOrder) then begin
CRMIntegrationRecord2.GetBySystemId(CRMIntegrationRecord.SystemId);
CRMIntegrationRecord2."Archived Service Order Updated" := true;
CRMIntegrationRecord2.Modify();
ModifyCounter += 1;
end;
until CRMIntegrationRecord.Next() = 0;

IntegrationTableSynch.UpdateSynchJobCounters(SynchActionType::Modify, ModifyCounter);
IntegrationTableSynch.EndIntegrationSynchJobWithMsg(ArchivedOrdersUpdatedMsg);
end;

[TryFunction]
local procedure UpdateFromServiceHeader(var FSWorkOrder: Record "FS Work Order")
begin
ResetFSWorkOrderLineFromServiceOrderLine(FSWorkOrder);
MarkPosted(FSWorkOrder);
end;

local procedure ResetFSWorkOrderLineFromServiceOrderLine(var FSWorkOrder: Record "FS Work Order")
var
ServiceLineArchive: Record "Service Line Archive";
FSWorkOrderProduct: Record "FS Work Order Product";
FSWorkOrderService: Record "FS Work Order Service";
CRMIntegrationRecord: Record "CRM Integration Record";
begin
FSWorkOrderProduct.SetRange(WorkOrder, FSWorkOrder.WorkOrderId);
if FSWorkOrderProduct.FindSet() then
repeat
if CRMIntegrationRecord.FindByCRMID(FSWorkOrderProduct.WorkOrderProductId) then
if ServiceLineArchive.GetBySystemId(CRMIntegrationRecord."Archived Service Line Id") then
UpdateWorkOrderProduct(ServiceLineArchive, FSWorkOrderProduct);
until FSWorkOrderProduct.Next() = 0;

FSWorkOrderService.SetRange(WorkOrder, FSWorkOrder.WorkOrderId);
if FSWorkOrderService.FindSet() then
repeat
if CRMIntegrationRecord.FindByCRMID(FSWorkOrderService.WorkOrderServiceId) then
if ServiceLineArchive.GetBySystemId(CRMIntegrationRecord."Archived Service Line Id") then
UpdateWorkOrderService(ServiceLineArchive, FSWorkOrderService);
until FSWorkOrderService.Next() = 0;
end;

local procedure MarkPosted(var FSWorkOrder: Record "FS Work Order")
begin
FSWorkOrder.SystemStatus := FSWorkOrder.SystemStatus::Posted;
FSWorkOrder.Modify();
end;

internal procedure UpdateWorkOrderProduct(ServiceLineArchive: Record "Service Line Archive"; var FSWorkOrderProduct: Record "FS Work Order Product")
var
Modified: Boolean;
begin
if FSWorkOrderProduct.QuantityShipped <> (ServiceLineArchive."Quantity Shipped" + ServiceLineArchive."Qty. to Ship") then begin
FSWorkOrderProduct.QuantityShipped := ServiceLineArchive."Quantity Shipped" + ServiceLineArchive."Qty. to Ship";
Modified := true;
end;

if FSWorkOrderProduct.QuantityInvoiced <> (ServiceLineArchive."Quantity Invoiced" + ServiceLineArchive."Qty. to Invoice") then begin
FSWorkOrderProduct.QuantityInvoiced := ServiceLineArchive."Quantity Invoiced" + ServiceLineArchive."Qty. to Invoice";
Modified := true;
end;

if FSWorkOrderProduct.QuantityConsumed <> ServiceLineArchive."Quantity Consumed" + ServiceLineArchive."Qty. to Consume" then begin
FSWorkOrderProduct.QuantityConsumed := ServiceLineArchive."Quantity Consumed" + ServiceLineArchive."Qty. to Consume";
Modified := true;
end;

if Modified then
FSWorkOrderProduct.Modify();
end;

internal procedure UpdateWorkOrderService(ServiceLineArchive: Record "Service Line Archive"; var FSWorkOrderService: Record "FS Work Order Service")
var
Modified: Boolean;
begin
if FSWorkOrderService.DurationShipped <> (ServiceLineArchive."Quantity Shipped" + ServiceLineArchive."Qty. to Ship") then begin
FSWorkOrderService.DurationShipped := (ServiceLineArchive."Quantity Shipped" + ServiceLineArchive."Qty. to Ship") * 60;
Modified := true;
end;

if FSWorkOrderService.DurationInvoiced <> (ServiceLineArchive."Quantity Invoiced" + ServiceLineArchive."Qty. to Invoice") then begin
FSWorkOrderService.DurationInvoiced := (ServiceLineArchive."Quantity Invoiced" + ServiceLineArchive."Qty. to Invoice") * 60;
Modified := true;
end;

if FSWorkOrderService.DurationConsumed <> ServiceLineArchive."Quantity Consumed" + ServiceLineArchive."Qty. to Consume" then begin
FSWorkOrderService.DurationConsumed := (ServiceLineArchive."Quantity Consumed" + ServiceLineArchive."Qty. to Consume") * 60;
Modified := true;
end;

if Modified then
FSWorkOrderService.Modify();
end;
}

Loading
Loading