/* **************************************************************************** Component Name : FieldMappingParent Created Date : 17/4/2024 @description : This component manages the mapping between Salesforce and Shopify fields. @author : SME Team Modification Log: Ver Date Author 1.0 23/4/2024 SME Team **************************************************************************** */ import { LightningElement, api, track, wire } from "lwc"; // FETCHING RESOURCES FROM THE STATIC RESOURCES // import pageLoadingGif from "@salesforce/resourceUrl/SMEPageLoadingGif"; import Resources from "@salesforce/resourceUrl/Resources"; import SMEPageLoadingGIF2 from "@salesforce/resourceUrl/SMEPageLoadingGIF2"; // get the default account import getDefaultAccForConts from "@salesforce/apex/ShopifyController.getDefaultAccForConts"; import getAccountDetails from "@salesforce/apex/ShopifyController.getAccountDetails"; // get default opp close date import getDefaultOppClosedate from "@salesforce/apex/ShopifyController.getDefaultOppClosedate"; // get default opportunity stage import getDefaultOppStage from "@salesforce/apex/ShopifyController.getDefaultOppStage"; // call delete row import deleteFieldMappings from "@salesforce/apex/ShopifyController.deleteFieldMappings"; import fetchLookupData from '@salesforce/apex/ShopifyController.fetchLookupData'; import fetchDefaultRecord from '@salesforce/apex/ShopifyController.fetchDefaultRecord'; import fetchAccount from "@salesforce/apex/ShopifyController.fetchAccount"; import getConfigrationForDynamicRow from '@salesforce/apex/ShopifyController.getConfigrationForDynamicRow'; // import getFieldMappings from '@salesforce/apex/ShopifyController.getFieldMappings'; import getFieldMappings from '@salesforce/apex/ShopifyController.getObjectFieldMapping'; import updateFieldMappingAndConfigration from '@salesforce/apex/ShopifyController.updateFieldMappingAndConfigration'; // ALL active Opportunity stages via SOQL on OpportunityStage — not limited to the // default record type's picklist assignment like the UI API getPicklistValues wire, // so newly added stages always show up. import getOpportunityStages from "@salesforce/apex/ShopifyController.getOpportunityStages"; // SHOW TOAST import { ShowToastEvent } from "lightning/platformShowToastEvent"; //Custom Labels import Customer_Settings from '@salesforce/label/c.Customer_Settings'; import Default_Mapping_Information from '@salesforce/label/c.Default_Mapping_Information'; import SYNC_ALL_CONTACT from '@salesforce/label/c.SYNC_ALL_CONTACT'; import No_Records_Found from '@salesforce/label/c.No_Records_Found'; import Please_select_any_Account from '@salesforce/label/c.Please_select_any_Account'; import default_mapping_of_all_objects from '@salesforce/label/c.default_mapping_of_all_objects'; import Opportunity_Settings from '@salesforce/label/c.Opportunity_Settings'; import GIVE_DEFAULT_CLOSE_DATE from '@salesforce/label/c.GIVE_DEFAULT_CLOSE_DATE'; import This_is_a_required_field from '@salesforce/label/c.This_is_a_required_field'; import DEFAULT_STAGE from '@salesforce/label/c.DEFAULT_STAGE'; import Account from '@salesforce/label/c.Account'; import Contact from '@salesforce/label/c.Contact'; import Opportunity from '@salesforce/label/c.Opportunity'; import Draft_Order from '@salesforce/label/c.Draft_Order'; import Product from '@salesforce/label/c.Product'; import Order from '@salesforce/label/c.Order'; import Variant from '@salesforce/label/c.Variant'; import Error from '@salesforce/label/c.Error'; import Required_Field_Missing_in from '@salesforce/label/c.Required_Field_Missing_in'; import Please_enter_the_number_of_days from '@salesforce/label/c.Please_enter_the_number_of_days'; import Please_select_the_stage from '@salesforce/label/c.Please_select_the_stage'; import Search_Accounts from '@salesforce/label/c.Search_Accounts'; import Days from '@salesforce/label/c.Days'; import Status from '@salesforce/label/c.Status'; import Select_status from '@salesforce/label/c.Select_status'; import ClosedDateInformation from '@salesforce/label/c.ClosedDateInformation'; import ContactOrderSingleAccount from '@salesforce/label/c.ContactOrderSingleAccount'; export default class FieldMappingParent extends LightningElement { // Custom in-component toast state (replaces ShowToastEvent) — see showNotification. @track toasts = []; _toastSeq = 0; // GLOBAL VARIABLES @api storeName = ""; @api storeSelectionType = ""; @api isNewStore; @api fieldMappings = ""; // GLOBAL VARIABLES with initial default values @api label = 'custom lookup label'; @api placeholder = 'Search Accounts...'; @api iconName = 'standard:account'; @api sObjectApiName = 'Account'; @api defaultRecordId = ''; // LOCAL VARIABLES @track configObject = {}; @track requiredMappingPersonAcc = []; @track objectFieldsList = []; defaultStage = null; @track searchKey; @track daysValue = null; @track selectedValue; @track accounts = []; @track accountId = null; @track useDefault = true; @track showAccountDropdown = false; @track isNotPersonAccount = true; @track accountDefaultMapping = []; @track allChildValues = []; // Store Contact Object List @track accountList = []; @track contactList = []; @track orderList = []; @track orderProductList = []; @track draftOrderList = []; @track draftOrderProductList = []; @track opportunityList = []; @track opportunityProductList = []; @track variantList = []; @track productList = []; @track oppDefault = false; @track errorObjectName = []; @track isAccountLookupEmpty = false; @track isDaysEmpty = false; @track isAlpha = false; @track isDaysGreater = false; @track isLeapYear = false; @track isDaysLess = false; @track inputError = ''; @track configChanged = false; @track isLoading = false; @track deletedRowList = []; //Custom Labels @track label = { Customer_Settings,Default_Mapping_Information, SYNC_ALL_CONTACT, No_Records_Found, Please_select_any_Account, default_mapping_of_all_objects, ClosedDateInformation, ContactOrderSingleAccount, Opportunity_Settings, GIVE_DEFAULT_CLOSE_DATE, This_is_a_required_field, DEFAULT_STAGE, Account, Opportunity, Contact, Draft_Order, Product, Order, Variant, Error, Required_Field_Missing_in, Please_enter_the_number_of_days, Please_select_the_stage, Search_Accounts, Days, Status, Select_status }; // pageLoadingGif = pageLoadingGif; pageLoadingGif = SMEPageLoadingGIF2; // private properties for custom lookup code for account accounts = []; // to store list of returned records hasRecords = true; searchKey = ''; // to store input field value isSearchLoading = false; // to control loading spinner delayTimeout; selectedRecord = {}; // to store selected lookup record in object formate //Connected Callback Method connectedCallback() { console.log('SYNC MADE EASY: Field Mapping Parent Connected Callback'); this.showSpinnerHandler(); this.getconfigrationForDynamicRow(); this.getFieldMappings(); } get isOpportunityConfigEnabled() { return this.configObject.HIC_ShopifySync__Opportunity__c || this.configObject.HIC_ShopifySync__Enable_Opportunity_for_SDO__c; } //This method get the store details getconfigrationForDynamicRow() { console.log('SYNC MADE EASY: Field Mapping Parent => Fetching Store Details'); getConfigrationForDynamicRow({ store: this.storeName }).then((result) => { this.configObject = JSON.parse(result); this.useDefault = this.configObject.HIC_ShopifySync__Default_Field_Mapping__c; this.masterToggleVisualOn = this.useDefault; this.oppDefault = !this.configObject.HIC_ShopifySync__Default_Field_Mapping__c; if (!this.useDefault && this.oppDefault) { this.getDefaultOpportunityClosedate(); } if (this.configObject.HIC_ShopifySync__Person_Account__c) { this.isNotPersonAccount = false; } if (this.configObject.hasOwnProperty('HIC_ShopifySync__Default_Account__c') && this.configObject.HIC_ShopifySync__Default_Account__c) { this.getDefaultAccForContact(); } this.getDefaultOpportunityStageHandler(); }).catch((error) => { this.closeSpinnerHandler(); }); this.controlListView(); } // ALL active Opportunity stages (label/value), ordered by SortOrder @track stageOptions = []; @wire(getOpportunityStages) wiredStages({ error, data }) { if (data) { this.stageOptions = data; } else if (error) { console.log('@@@ getOpportunityStages error : ' + JSON.stringify(error)); } } get hasStageOptions() { return this.stageOptions && this.stageOptions.length > 0; } // This method handles the Default stage onchange in Opportunity Settings changeStage(event) { this.configChanged = true; this.defaultStage = event.detail.value; } //Sync Account with the Orders syncAccount() { this.configChanged = true; if (this.configObject.hasOwnProperty('HIC_ShopifySync__Default_Account__c') && this.configObject.HIC_ShopifySync__Default_Account__c !== null) { this.configObject.HIC_ShopifySync__Default_Account__c = !this.configObject.HIC_ShopifySync__Default_Account__c; } this.controlListView(); } //OPPORTUNITY CLOSE DATE TOGGLE HANDLER opportunityCloseDate() { try { this.configObject.HIC_ShopifySync__Specify_Close_Date__c = this.configObject.HIC_ShopifySync__Specify_Close_Date__c; // 🔹 If toggle is turned ON → reset everything if (!this.configObject.HIC_ShopifySync__Specify_Close_Date__c) { this.daysValue = null; this.isAlpha = false; this.isDaysGreater = false; this.isDaysLess = false; this.isLeapYear = false; } let element = this.template.querySelector('[data-id="${this.label.Opportunity}"]'); if (element) { this.template.querySelector('[data-id="${this.label.Opportunity}"]').removeCloseDate(); } } catch (error) { console.error('ERROR OCCURED AT LINE +' + JSON.stringify(error)); } this.configChanged = true; this.configObject.HIC_ShopifySync__Specify_Close_Date__c = !this.configObject.HIC_ShopifySync__Specify_Close_Date__c; this.removeOppRequiredClosedDate(); } // Method to remove close date from the opportunity required mapping when removeOppRequiredClosedDate() { let removeClosedDateRequired = this.opportunityList; let indexNumber = 1; this.opportunityList = removeClosedDateRequired.map((obj) => { if (obj.HIC_ShopifySync__External_ID.toUpperCase() === "OPPORTUNITY-CLOSEDATE") { indexNumber = this.opportunityList.indexOf(obj); if (this.configObject.HIC_ShopifySync__Specify_Close_Date__c) { obj.showRecords = false; obj.selectedfields = null; obj.graphqlfield = null; obj.defaultValue = false; obj.defaultCheckboxDisabled = true; } else if (!this.configObject.HIC_ShopifySync__Specify_Close_Date__c && obj.selectedfields === null) { obj.defaultValue = false; obj.defaultCheckboxDisabled = true; obj.showRecords = true; this.daysValue = null; obj.showError = true; } if ((!this.configObject.HIC_ShopifySync__Specify_Close_Date__c && obj.selectedfields !== null) || (this.configObject.HIC_ShopifySync__Specify_Close_Date__c)) { obj.showError = false; this.isDaysEmpty = false; this.errorObjectName.pop(obj.sobjectType); } else { obj.showError = true; this.isDaysEmpty = true; this.errorObjectName.push(obj.sobjectType); } } else if (obj.HIC_ShopifySync__External_ID.toUpperCase() !== "OPPORTUNITY-CLOSEDATE" && obj.showError && !this.errorObjectName.includes(obj.sobjectType) && (!this.useDefault || this.oppDefault)) { this.errorObjectName.push(obj.sobjectType); } return obj; }); } //This method gets fieldMapping of Different Objects. getFieldMappings() { this.showSpinnerHandler(); console.log('SYNC MADE EASY: Field Mapping Parent => Fetching Fields Mapping'); let objectList = ["Product2", "HIC_ShopifySync__Variant__c", "Account", "Contact", "DraftOrder", "DraftOrderItem", "Order", "OrderItem", "Opportunity", "OpportunityLineItem"]; let duplicateObjectList = []; for (let objectName of objectList) { duplicateObjectList.push(objectName); //objectList.splice(0, 1); console.log('SYNC MADE EASY: Field Mapping Parent => Fetching Fields : ' + objectName); console.log('SYNC MADE EASY: Field Mapping Parent => Fetching Fields this.objectList : ' + objectList); console.log('SYNC MADE EASY: Field Mapping Parent => Fetching Fields this.objectList : ' + duplicateObjectList); getFieldMappings({ storeName: this.storeName, objectName: objectName }).then((result) => { if (result) { let parsedresult = JSON.parse(result); const objectMapping = new Map(); if (parsedresult.hasOwnProperty('Product2')) { objectMapping.set("Product2", JSON.parse(parsedresult.Product2)); } if (parsedresult.hasOwnProperty('HIC_ShopifySync__Variant__c')) { objectMapping.set("HIC_ShopifySync__Variant__c", JSON.parse(parsedresult.HIC_ShopifySync__Variant__c)); } if (parsedresult.hasOwnProperty('Account')) { objectMapping.set("Account", JSON.parse(parsedresult.Account)); } if (parsedresult.hasOwnProperty('Contact')) { objectMapping.set("Contact", JSON.parse(parsedresult.Contact)); } if (parsedresult.hasOwnProperty('Order')) { objectMapping.set("Order", JSON.parse(parsedresult.Order)); } if (parsedresult.hasOwnProperty('OrderItem')) { objectMapping.set("OrderItem", JSON.parse(parsedresult.OrderItem)); } if (parsedresult.hasOwnProperty('DraftOrder')) { objectMapping.set("DraftOrder", JSON.parse(parsedresult.DraftOrder)); } if (parsedresult.hasOwnProperty('DraftOrderItem')) { objectMapping.set("DraftOrderItem", JSON.parse(parsedresult.DraftOrderItem)); } if (parsedresult.hasOwnProperty('Opportunity')) { objectMapping.set("Opportunity", JSON.parse(parsedresult.Opportunity)); } if (parsedresult.hasOwnProperty('OpportunityLineItem')) { objectMapping.set("OpportunityLineItem", JSON.parse(parsedresult.OpportunityLineItem)); } for (let [key, value] of objectMapping) { if (key == "Account" && JSON.parse(parsedresult.Account).personAccountFields) { this.requiredMappingPersonAcc = JSON.parse(parsedresult.Account).personAccountFields; } this.objectFieldsList.push({ priortyNumber: 1, objectName: key, objectApiName: key, iconName: "standard:account", showList: true, openTable: false, defaultMapping: value.defaultMapping, shopifyFields: value.shopifyFields, salesforceFields: value.optionalFields, requiredMapping: value.requiredFields }); }; if (objectList.length === duplicateObjectList.length) { console.log('>>> Arrayrs are same :: '); this.closeSpinnerHandler(); } // this.showSpinnerHandler(); this.updatedObjectField(); } else { console.log('>>> Object not selected :: ' + objectList); if (objectList.length === duplicateObjectList.length) { console.log('>>> Arrayrs are same :: '); this.closeSpinnerHandler(); } } }).catch((error) => { console.log('ERROR OCCURED :: ' + error); console.log('>>> Object got Error :: ' + objectList); this.closeSpinnerHandler(); }); } } //This method is updating fields of different objects updatedObjectField() { if (this.objectFieldsList) { let everthingObjectList = this.objectFieldsList; this.objectFieldsList = everthingObjectList.map((obj) => { if (obj.objectApiName == "Account") { obj.priortyNumber = 3; obj.objectName = this.label.Account; obj.iconName = "standard:account"; } else if (obj.objectApiName == "Contact") { obj.priortyNumber = 4; obj.objectName = this.label.Contact; obj.iconName = "standard:contact"; } else if (obj.objectApiName == "Opportunity") { obj.priortyNumber = 9; obj.objectName = this.label.Opportunity; obj.iconName = "standard:opportunity"; } else if (obj.objectApiName == "OpportunityLineItem") { obj.priortyNumber = 10; obj.objectName = this.label.Opportunity + ' ' + this.label.Product; obj.iconName = "standard:product"; } else if (obj.objectApiName == "DraftOrderItem") { obj.priortyNumber = 6; obj.objectName = this.label.Draft_Order + ' ' + this.label.Product; // obj.iconName= "standard:product"; obj.iconName = "standard:return_order"; } else if (obj.objectApiName == "DraftOrder") { obj.priortyNumber = 5; obj.objectName = this.label.Draft_Order; // obj.iconName= "standard:orders"; obj.iconName = "standard:return_order_line_item"; } else if (obj.objectApiName == "OrderItem") { obj.priortyNumber = 8; obj.objectName = this.label.Order + ' ' + this.label.Product; // obj.iconName= "standard:product"; obj.iconName = "standard:product_item"; } else if (obj.objectApiName == "Order") { obj.priortyNumber = 7; obj.objectName = this.label.Order; obj.iconName = "standard:orders"; } else if (obj.objectApiName == "HIC_ShopifySync__Variant__c") { obj.priortyNumber = 2; obj.objectName = this.label.Variant; obj.iconName = "standard:product"; } else if (obj.objectApiName == "Product2") { obj.priortyNumber = 1; obj.objectName = this.label.Product; // obj.iconName= "standard:orders"; obj.iconName = "standard:product"; } return obj; }); this.shortListView(); } else { this.closeSpinnerHandler(); } // if (this.objectList.length = 0) { // console.log('@@@ length is zero : ', this.objectList); // this.closeSpinnerHandler(); // } } // This method gets default account for contact getDefaultAccForContact() { console.log('SYNC MADE EASY: Field Mapping Parent => Fetching Default Account'); getDefaultAccForConts({ store: this.storeName }) .then((result) => { if (result != null) { let accId = result?.HIC_ShopifySync__Shopify_Fields__c; if (result && !accId.includes('id')) { getAccountDetails({ accId: accId }).then((result) => { console.log('SYNC MADE EASY: Field Mapping Parent => Fetching Default Account Details'); if (result != null) { this.accounts.push(result); this.accountId = result.Id; this.searchKey = result.Name; fetchDefaultRecord({ recordId: this.accountId, 'sObjectApiName': this.sObjectApiName }).then((result) => { if (result != null) { this.selectedRecord = result; this.handelSelectRecordHelper(); // helper function to show/hide lookup result container on UI } }).catch((error) => { this.error = error; this.selectedRecord = {}; this.closeSpinnerHandler(); }); } }) .catch((error) => { this.closeSpinnerHandler(); }); } } }) .catch((error) => { this.closeSpinnerHandler(); }); } // METHOD TO GET DEFAULT CLOSE DATE getDefaultOpportunityClosedate() { console.log('SYNC MADE EASY: Field Mapping Parent => Fetching Default Opportunity Close Date'); getDefaultOppClosedate({ store: this.storeName }) .then((result) => { if (result?.HIC_ShopifySync__Default_Value__c) { this.daysValue = result?.HIC_ShopifySync__Shopify_Fields__c; } }) .catch((error) => { this.closeSpinnerHandler(); }); } // METHOD TO GET DEFAULT STAGE getDefaultOpportunityStageHandler() { console.log('SYNC MADE EASY: Field Mapping Parent => Fetching Default Opportunity Stage Name'); getDefaultOppStage({ store: this.storeName }) .then((result) => { if (result) { this.defaultStage = result; } }) .catch((error) => { this.closeSpinnerHandler(); }); } //This method controls the list of objects visiblity on Field Mapping step controlListView() { let listToBeShorted = this.objectFieldsList; this.objectFieldsList = listToBeShorted.map((obj) => { if (this.configObject.hasOwnProperty('HIC_ShopifySync__Default_Account__c') && this.configObject.HIC_ShopifySync__Default_Account__c && (obj.objectApiName == 'Account' || obj.objectApiName == 'PersonAccount')) { obj.showList = false; } else if (this.configObject.hasOwnProperty('HIC_ShopifySync__Default_Account__c') && !this.configObject.HIC_ShopifySync__Default_Account__c && (obj.objectApiName == 'Account' || obj.objectApiName == 'PersonAccount')) { obj.showList = true; } if (this.configObject.HIC_ShopifySync__Person_Account__c && obj.objectApiName == 'Account') { obj.objectName = 'Person Account'; obj.objectApiName = 'PersonAccount'; obj.requiredMapping = this.requiredMappingPersonAcc; } if (this.configObject.HIC_ShopifySync__Account_Contact__c && obj.objectApiName == 'Contact') { obj.showList = true; } else if (!this.configObject.HIC_ShopifySync__Account_Contact__c && obj.objectApiName == 'Contact') { obj.showList = false; } if (this.configObject.HIC_ShopifySync__Product_Sync__c && obj.objectApiName == 'Product2') { obj.showList = true; } else if (!this.configObject.HIC_ShopifySync__Product_Sync__c && obj.objectApiName == 'Product2') { obj.showList = false; } if (this.configObject.HIC_ShopifySync__Product_Sync__c && obj.objectApiName == 'HIC_ShopifySync__Variant__c') { obj.showList = true; } else if (!this.configObject.HIC_ShopifySync__Product_Sync__c && obj.objectApiName == 'HIC_ShopifySync__Variant__c') { obj.showList = false; } if (this.configObject.HIC_ShopifySync__Order__c && obj.objectApiName == 'Order') { obj.showList = true; } else if (!this.configObject.HIC_ShopifySync__Order__c && obj.objectApiName == 'Order') { obj.showList = false; } if (this.configObject.HIC_ShopifySync__Order__c && obj.objectApiName == 'OrderItem') { obj.showList = true; } else if (!this.configObject.HIC_ShopifySync__Order__c && obj.objectApiName == 'OrderItem') { obj.showList = false; } if (this.configObject.HIC_ShopifySync__Enable_Draft_Order__c && obj.objectApiName == 'DraftOrder') { obj.showList = true; } else if (!this.configObject.HIC_ShopifySync__Enable_Draft_Order__c && obj.objectApiName == 'DraftOrder') { obj.showList = false; } if (this.configObject.HIC_ShopifySync__Enable_Draft_Order__c && obj.objectApiName == 'DraftOrderItem') { obj.showList = true; } else if (!this.configObject.HIC_ShopifySync__Enable_Draft_Order__c && obj.objectApiName == 'DraftOrderItem') { obj.showList = false; } if ((this.configObject.HIC_ShopifySync__Opportunity__c || this.configObject.HIC_ShopifySync__Enable_Opportunity_for_SDO__c) && obj.objectApiName == 'Opportunity') { obj.showList = true; } else if (!this.configObject.HIC_ShopifySync__Opportunity__c && !this.configObject.HIC_ShopifySync__Enable_Opportunity_for_SDO__c && obj.objectApiName == 'Opportunity') { obj.showList = false; } if ((this.configObject.HIC_ShopifySync__Opportunity_Line_Item__c || this.configObject.HIC_ShopifySync__Enable_Opportunity_for_SDO__c) && obj.objectApiName == 'OpportunityLineItem') { obj.showList = true; } else if (!this.configObject.HIC_ShopifySync__Opportunity_Line_Item__c && !this.configObject.HIC_ShopifySync__Enable_Opportunity_for_SDO__c && obj.objectApiName == 'OpportunityLineItem') { obj.showList = false; } return obj; }); this.closeSpinnerHandler(); } //This method is responsible for the order of objects in the List on Field Mapping step shortListView() { let listToBeShorted = this.objectFieldsList; this.objectFieldsList = listToBeShorted.sort((p1, p2) => (p1.priortyNumber > p2.priortyNumber) ? 1 : (p1.priortyNumber < p2.priortyNumber) ? -1 : 0); this.controlListView(); } //This method handles the Search Account input box values from UI and Get list of Account based on search keyword fetchAccount(event) { this.isSearchLoading = true; this.searchKey = event.target.value; if (!event.target.value) { this.accountId = null; } console.log('SYNC MADE EASY: Field Mapping Parent => Fetch Accounts'); fetchAccount({ searchKeyWord: this.searchKey }) .then((result) => { this.accounts = result; this.hasRecords = result.length == 0 ? false : true; // this.accounts = result; this.isSearchLoading = false; }) .catch((error) => { this.closeSpinnerHandler(); }); } // STORE CHANGE DAYS daysChange(event) { const value = event.target.value; // Reset flags this.isAlpha = false; this.isDaysGreater = false; this.isDaysLess = false; this.isLeapYear= false; // 🔹 1. Alphabet check if (value && !/^\d+$/.test(value)) { this.isAlpha = true; this.daysValue = null; event.target.value = null; return; } const numericValue = Number(value); this.daysValue = value; // 🔹 2. Get Current Year const currentYear = new Date().getFullYear(); // 🔹 3. Leap Year Check const isLeapYear = (currentYear % 4 === 0 && currentYear % 100 !== 0) || (currentYear % 400 === 0); // 🔹 4. Set Max Days Based on Year const maxDays = isLeapYear ? 366 : 365; // 🔹 5. Greater than allowed days if (numericValue > maxDays) { if(maxDays==366){ this.isLeapYear = true; }else{ this.isDaysGreater = true; } this.daysValue = null; event.target.value = null; return; } // 🔹 6. Less than or equal to 0 if (numericValue <= 0) { this.isDaysLess = true; this.daysValue = null; event.target.value = null; return; } // ✅ Valid this.removeOppRequiredClosedDate(); } // daysChange(event) { // this.daysValue = event.target.value; // if (this.daysValue > 365) { // this.daysValue = 365; // } // if (this.daysValue < 0) { // this.daysValue = 0; // } // this.removeOppRequiredClosedDate(); // } // Account Selected Processing selectedAccount(event) { for (let account of this.accounts) { if (event.target.dataset.value == account.Id) { this.searchKey = account.Name; this.accountId = account.Id; this.showAccountDropdown = false; } } } //This method handles the DEFAULT MAPPING OF ALL OBJECTS toggle's onchange value handleSyncList(event) { this.configChanged = true; let defaultChecked = event.target.checked; this.useDefault = defaultChecked; this.oppDefault = !this.useDefault; this.configObject.HIC_ShopifySync__Default_Field_Mapping__c = this.useDefault; this.removeOppRequiredClosedDate(); if (!this.useDefault && this.oppDefault) { this.getDefaultOpportunityClosedate(); this.getDefaultOpportunityStageHandler(); // this.removeOppRequiredClosedDate(); } } // GET VALUES FROM CHILD FIELD MAPPING COMPONENT changedvalueschildHandler(event) { let childvalues = event.detail.value; let childobj = event.detail.obj; console.log('This is ChildObj>>>>>', childobj); childobj = childobj.replace("Field Mapping", "").trim(); if (childobj == this.label.Account || childobj == 'Person Account' || childobj == 'PersonAccount') { this.accountList = []; this.accountList.push(...childvalues); } if (childobj == this.label.Contact) { this.contactList = []; this.contactList.push(...childvalues); } if (childobj == this.label.Order) { this.orderList = []; this.orderList.push(...childvalues); } if (childobj == this.label.Order + ' ' + this.label.Product) { this.orderProductList = []; this.orderProductList.push(...childvalues); } if (childobj == this.label.Draft_Order) { this.draftOrderList = []; this.draftOrderList.push(...childvalues); } if (childobj == this.label.Draft_Order + ' ' + this.label.Product) { this.draftOrderProductList = []; this.draftOrderProductList.push(...childvalues); } if (childobj == this.label.Opportunity) { this.opportunityList = []; this.opportunityList.push(...childvalues); this.removeOppRequiredClosedDate(); } if (childobj == this.label.Opportunity + ' ' + this.label.Product) { this.opportunityProductList = []; this.opportunityProductList.push(...childvalues); } if (childobj == this.label.Variant) { this.variantList = []; this.variantList.push(...childvalues); } if (childobj == this.label.Product) { this.productList = []; this.productList.push(...childvalues); } } //This the method to store the Salesforce Id of Deleted row records deletedRowChildHandler(event) { let deleteChildValues = event.detail; this.deletedRowList.push(...deleteChildValues); } //This method handling the default mapping toggle for Opportunity enableOpportunity(event) { this.configChanged = true; this.oppDefault = event.detail.value; this.removeOppRequiredClosedDate(); // get the close date if (this.oppDefault) { this.getDefaultOpportunityClosedate(); this.getDefaultOpportunityStageHandler(); } } // REQUIRED FILED MISSING ERROR Method Handler requiredFieldMissing() { this.objectFieldsList.map((object) => { object.openTable = false; if (this.errorObjectName.includes(object.objectName)) { object.openTable = true; this.showNotification(this.label.Error, 'Error', this.label.Required_Field_Missing_in + ' ' + object.objectName); } }); } // This method only GET FIELD WHICH ARE NEW OR EDITED getNewOrEditedFields(recordList) { return recordList.filter((obj) => { if (obj.newOrEditedFields === true) { return true; } return false; }) } // ── Custom toggle getters (Step 3 pattern) ── get syncAccountToggleClass() { return 'obj-toggle-track' + (this.configObject.HIC_ShopifySync__Default_Account__c ? ' obj-toggle-track_on' : ''); } get defaultMappingToggleClass() { return 'obj-toggle-track' + (this.masterToggleVisualOn ? ' obj-toggle-track_on' : ''); } get closeDateToggleClass() { return 'obj-toggle-track' + (this.configObject.HIC_ShopifySync__Specify_Close_Date__c ? ' obj-toggle-track_on' : ''); } // ── Custom toggle click handlers ── handleSyncAccountToggle() { this.syncAccount(); } handleDefaultMappingToggle() { const newVal = !this.useDefault; this.handleSyncList({ target: { checked: newVal } }); // A manual click on the master toggle always cascades to every child, // so the master's own visual state should match immediately, and we // reset the per-object tracking (children haven't reported back yet). this.masterToggleVisualOn = newVal; this.childDefaultMappingState = {}; } // DISPLAY-ONLY: tracks each object row's own toggle state so the // "Default mapping of all objects" master toggle's *appearance* can // reflect them. This never writes to `this.useDefault` (the value // cascaded down to every child via use-default={useDefault}), so it // cannot feed back into the children and cause a loop. childDefaultMappingState = {}; handleChildDefaultChange(event) { const { objectName, useDefault } = event.detail; this.childDefaultMappingState = { ...this.childDefaultMappingState, [objectName]: useDefault }; const allStates = Object.values(this.childDefaultMappingState); this.masterToggleVisualOn = allStates.length > 0 && allStates.every((val) => val === true); } handleCloseDateToggle() { this.opportunityCloseDate(); } handleBackStep() { this.dispatchEvent(new CustomEvent('back')); } //This method saves the updated values of Field Mapping page @api handleSaveButton(event) { if (!(this.errorObjectName.length == 1 && this.errorObjectName.includes('Account') && this.configObject.hasOwnProperty('HIC_ShopifySync__Default_Account__c') && this.configObject.HIC_ShopifySync__Default_Account__c) && this.errorObjectName.length > 0) { this.requiredFieldMissing(); return; } this.showSpinnerHandler(); let listofRecord = []; listofRecord.push(...this.accountList); listofRecord.push(...this.contactList); listofRecord.push(...this.orderList); listofRecord.push(...this.orderProductList); listofRecord.push(...this.draftOrderList); listofRecord.push(...this.draftOrderProductList); listofRecord.push(...this.opportunityList); listofRecord.push(...this.opportunityProductList); listofRecord.push(...this.variantList); listofRecord.push(...this.productList); let checkingList = []; let defaultAccount = true; if (this.accountId && this.configObject.hasOwnProperty('HIC_ShopifySync__Default_Account__c') && this.configObject.HIC_ShopifySync__Default_Account__c) { this.isAccountLookupEmpty = false; let updatedList = listofRecord; listofRecord = updatedList.map((obj) => { if (obj.shopifyApiName === 'Contact-Accountid' || obj.shopifyApiName === 'Opportunity-Accountid' || obj.shopifyApiName === 'Order-Accountid' || obj.shopifyApiName === 'DraftOrder-Accountid') { obj.defaultValue = true; obj.selectedfields = this.accountId; obj.graphqlfield = this.accountId; obj.shopifyFieldType = 'String'; obj.newOrEditedFields = true; defaultAccount = false; } if (obj.shopifyApiName.toUpperCase().includes('CURRENCYISOCODE')) { checkingList.push(obj); } return obj; }); } else if (!this.accountId && this.configObject.hasOwnProperty('HIC_ShopifySync__Default_Account__c') && this.configObject.HIC_ShopifySync__Default_Account__c) { this.inputError = 'hasError'; this.isAccountLookupEmpty = true; this.showNotification(this.label.Error, 'Error', this.label.Please_select_any_Account); return; } else if (!this.accountId) { this.configObject.HIC_ShopifySync__Default_Account__c = false; } else { this.accountId = null; } if (this.daysValue && this.oppDefault && this.configObject.HIC_ShopifySync__Specify_Close_Date__c) { let updatedList = listofRecord; listofRecord = updatedList.map((obj) => { if (obj.shopifyApiName === 'Opportunity-CloseDate') { obj.defaultValue = true; obj.selectedfields = this.daysValue; obj.graphqlfield = this.daysValue; obj.shopifyFieldName = this.daysValue; obj.newOrEditedFields = true; } return obj; }); } else if (!this.daysValue && this.oppDefault && this.configObject.HIC_ShopifySync__Specify_Close_Date__c) { this.isDaysEmpty = true; this.showNotification(this.label.Error, 'Error', this.label.Please_enter_the_number_of_days); return; } if (this.defaultStage && this.oppDefault) { let updatedList = listofRecord; listofRecord = updatedList.map((obj) => { if (obj.shopifyApiName === 'Opportunity-StageName') { obj.defaultValue = true; obj.selectedfields = this.defaultStage; obj.graphqlfield = this.defaultStage; obj.newOrEditedFields = true; } return obj; }); } else if (!this.defaultStage && this.oppDefault) { // Show error when stage is not selected this.showNotification(this.label.Error, 'Error', this.label.Please_select_the_stage); return; } // This is the list of deleted row sent ot backend if (this.deletedRowList.length) { console.log('SYNC MADE EASY: Field Mapping Parent => Delete Selected Field Mappings'); deleteFieldMappings({ deletedCustomSetting: JSON.stringify(this.deletedRowList), store: this.storeName }) .then((result) => { if (result) { //Success } }).catch((error) => { this.closeSpinnerHandler(); }); } let updatedListofRecord = this.getNewOrEditedFields(listofRecord); this.saveFieldMappingAndConfigration(defaultAccount, updatedListofRecord); } // METHOD TO SAVE CONFIGRATION, FIELD MAPPING AND DEFAULT FIELD MAPPING saveFieldMappingAndConfigration(defaultAccount, updatedListofRecord) { console.log('SYNC MADE EASY: Field Mapping Parent => Saving Field Mappings'); let isDefaultAccount = null; let listofRecord = null; let configObject = JSON.stringify(this.configObject); if (!this.configChanged) { configObject = null; } if (updatedListofRecord !== null && updatedListofRecord !== 'undefined' && updatedListofRecord.length > 0) { listofRecord = JSON.stringify(updatedListofRecord); } if (!this.configObject.HIC_ShopifySync__Default_Account__c) { this.accountId = null; } if (defaultAccount) { isDefaultAccount = defaultAccount; } if (configObject || listofRecord || isDefaultAccount) { updateFieldMappingAndConfigration( { defaultAccount: isDefaultAccount, configObj: configObject, listofRecord: listofRecord, accountId: this.accountId, oppDefaultStage: this.defaultStage, oppCloseDays: this.daysValue, storeName: this.storeName } ).then((result) => { let proceedNext = true; if (configObject && !result.configration) { proceedNext = false; } if (listofRecord && !result.fieldMapping) { proceedNext = false; } if (isDefaultAccount && !result.defaultFieldMapping) { proceedNext = false; } if (proceedNext) { const selectStore = new CustomEvent("save", { detail: "Saved" }); this.dispatchEvent(selectStore); } else { this.closeSpinnerHandler(); } }).catch((error) => { console.error('<<<<< ERROR :::: ' + JSON.stringify(error)); this.closeSpinnerHandler(); }); } else { const selectStore = new CustomEvent("save", { detail: "Saved" }); this.dispatchEvent(selectStore); } } // wire function property to fetch search record based on user input @wire(fetchLookupData, { searchKey: '$searchKey', sObjectApiName: '$sObjectApiName' }) searchResult(value) { console.log('SYNC MADE EASY: Field Mapping Parent => Fetching lookup data'); const { data, error } = value; // destructure the provisioned value this.isSearchLoading = false; if (data) { this.hasRecords = data.length == 0 ? false : true; this.accounts = JSON.parse(JSON.stringify(data)); } else if (error) { //Error occured } }; // This method updates searchKey property on input field change handleKeyChange(event) { // Debouncing this method: Do not update the reactive property as long as this function is // being called within a delay of DELAY. This is to avoid a very large number of Apex method calls. this.isSearchLoading = true; clearTimeout(this.delayTimeout); const searchKey = event.target.value; this.delayTimeout = setTimeout(() => { this.searchKey = searchKey; }, 5000); } // This method shows Account records result dropdown on UI on clicking on the Search Accounts input bar toggleResult(event) { this.configChanged = true; const lookupInputContainer = this.template.querySelector('.lookupInputContainer'); const clsList = lookupInputContainer.classList; const whichEvent = event.target.getAttribute('data-source'); switch (whichEvent) { case 'searchInputField': clsList.add('slds-is-open'); break; case 'lookupContainer': clsList.remove('slds-is-open'); break; } } // method to clear selected lookup record handleRemove() { this.searchKey = ''; this.accountId = null; this.selectedRecord = {}; // remove selected pill and display input field again const searchBoxWrapper = this.template.querySelector('.searchBoxWrapper'); searchBoxWrapper.classList.remove('slds-hide'); searchBoxWrapper.classList.add('slds-show'); const pillDiv = this.template.querySelector('.pillDiv'); pillDiv.classList.remove('slds-show'); pillDiv.classList.add('slds-hide'); } // method to update selected record from search result handelSelectedRecord(event) { this.accountId = event.target.getAttribute('data-recid'); // get selected record Id if (!this.accountId) { this.isAccountLookupEmpty = true; } else { this.isAccountLookupEmpty = false; } this.selectedRecord = this.accounts.find(data => data.Id === this.accountId); // find selected record from list this.handelSelectRecordHelper(); // helper function to show/hide lookup result container on UI } //This helper function is used to show/hide lookup result container on UI handelSelectRecordHelper() { try { this.template.querySelector('.lookupInputContainer').classList.remove('slds-is-open'); const searchBoxWrapper = this.template.querySelector('.searchBoxWrapper'); searchBoxWrapper.classList.remove('slds-show'); searchBoxWrapper.classList.add('slds-hide'); const pillDiv = this.template.querySelector('.pillDiv'); pillDiv.classList.remove('slds-hide'); pillDiv.classList.add('slds-show'); } catch (error) { } } //This method is used to show error objects when fields are empty showFieldErrorMsg(event) { let requiredFieldMapping = event.detail.requiredFields; let hasError = false; if (requiredFieldMapping !== null) { let emptyObject = requiredFieldMapping.filter((obj) => { if (obj.showError === true) { hasError = true; } }); } if (hasError) { if (!this.errorObjectName.includes(event.detail.objectName)) { this.errorObjectName.push(event.detail.objectName); } } else { const objIndex = this.errorObjectName.indexOf(event.detail.objectName); if (objIndex !== -1) { this.errorObjectName.splice(objIndex, 1); } } } //This Method is used to close spinner closeSpinnerHandler() { this.isLoading = false; const stopSpinner = new CustomEvent('closespinner', { detail: 'Stop Spinner' }); this.dispatchEvent(stopSpinner); } //This Method is used to show spinner showSpinnerHandler() { this.isLoading = true; const startSpinner = new CustomEvent('showspinner', { detail: 'Start Spinner' }); this.dispatchEvent(startSpinner); } //Helps to Show a Toast Message // Custom brand toast instead of ShowToastEvent. Same signature/callers. showNotification(title, variant, message) { const v = (variant || '').toString().toLowerCase(); const kind = v === 'error' ? 'error' : v === 'success' ? 'success' : v === 'warning' ? 'warning' : 'info'; const id = 't' + (this._toastSeq++); this.toasts = [...this.toasts, { id, title, message, cssClass: 'sw-toast sw-toast-' + kind, iconLabel: kind === 'error' ? '⚠' : kind === 'success' ? '✓' : kind === 'warning' ? '!' : 'ℹ' }]; if (kind !== 'error') { // eslint-disable-next-line @lwc/lwc/no-async-operation setTimeout(() => this._dismissToast(id), 4000); } this.closeSpinnerHandler(); } _dismissToast(id) { this.toasts = this.toasts.filter((t) => t.id !== id); } handleToastClose(event) { this._dismissToast(event.currentTarget.dataset.id); } }