/* **************************************************************************** Component Name : Finished Created Date : 17/4/2024 @description : This component handles the batch processing of objects and reports. @author : SME Team Modification Log: Ver Date Author 1.0 23/4/2024 SME Team **************************************************************************** */ import { LightningElement, track, api, wire } from 'lwc'; // FETCHING URLS FROM THE STATIC RESOURCES // import Youtube_sync from '@salesforce/resourceUrl/Youtube_sync'; // import Instagram_Sync from '@salesforce/resourceUrl/Instagram_Sync'; // import Twitter_sync from '@salesforce/resourceUrl/Twitter_sync'; // import LinkedIn_Sync from '@salesforce/resourceUrl/LinkedIn_Sync'; // FETCHING IMAGES FROM STATIC RESOURCES import Heart from '@salesforce/resourceUrl/Heart'; import image from '@salesforce/resourceUrl/SendingMailFalse'; import Rating from '@salesforce/resourceUrl/SME_Rating_bar'; // import Review_icon from '@salesforce/resourceUrl/Review_icon'; // import Newsletter_icon from '@salesforce/resourceUrl/Newsletter_icon'; // import Catvideo_icon from '@salesforce/resourceUrl/Catvideo_icon'; import Resources from "@salesforce/resourceUrl/Resources"; import StoreLogo from '@salesforce/resourceUrl/StoreLogo'; import user1Image from '@salesforce/resourceUrl/user1'; import user2Image from '@salesforce/resourceUrl/user2'; import user3Image from '@salesforce/resourceUrl/user3'; // CREATING INSTANCES OF APEX METHODS import updateAutoConfiguration from '@salesforce/apex/ShopifyController.updateAutoConfiguration'; import getConfigrationForDynamicRow from '@salesforce/apex/ShopifyController.getConfigrationForDynamicRow'; import syncShopify from '@salesforce/apex/ShopifyController.syncShopify'; import updateconfigurationpbatchprocessingfield from '@salesforce/apex/ShopifyController.updateconfigurationpbatchprocessingfield'; import getErrorMailList from '@salesforce/apex/ShopifyController.getErrorMailList'; import getWriteReviewURL from '@salesforce/apex/ShopifyController.getWriteReviewURL'; import CheckingBatchDetails from '@salesforce/apex/ShopifyController.CheckingBatchDetails'; import getShopifyRecordCounts from '@salesforce/apex/ShopifyController.getShopifyRecordCounts'; import getIsPerson from '@salesforce/apex/ShopifyController.getIsPerson'; import getGeneral from '@salesforce/apex/ShopifyController.getGeneral'; import getReports from '@salesforce/apex/ShopifyController.getReports'; // Abort batch method import abortBatch from '@salesforce/apex/ShopifyController.abortBatch'; import { NavigationMixin } from 'lightning/navigation'; //Custom Labels import Close from '@salesforce/label/c.Close'; import Final_Page_First_error from '@salesforce/label/c.Final_Page_First_error'; import for_more_help_contact_us_at from '@salesforce/label/c.for_more_help_contact_us_at'; import Process_re_again from '@salesforce/label/c.Process_re_again'; import Configure_Re_Again from '@salesforce/label/c.Configure_Re_Again'; import Thank_you_for_using from '@salesforce/label/c.Thank_you_for_using'; import Sync_Made_Easy from '@salesforce/label/c.Sync_Made_Easy'; import We_will_send_you_an_email from '@salesforce/label/c.We_will_send_you_an_email'; import Currently_Syncing from '@salesforce/label/c.Currently_Syncing'; import Batch_Status from '@salesforce/label/c.Batch_Status'; import Notification_will_be_sent_on_below_emails from '@salesforce/label/c.Notification_will_be_sent_on_below_emails'; import Open_Report from '@salesforce/label/c.Open_Report'; import Built_with from '@salesforce/label/c.Built_with'; import by_HIC_Global_Solutions from '@salesforce/label/c.by_HIC_Global_Solutions'; import Oops_Some_Error_occurred from '@salesforce/label/c.Oops_Some_Error_occurred'; import Complete from '@salesforce/label/c.Complete'; import In_Progress from '@salesforce/label/c.In_Progress'; import notStartedYet from '@salesforce/label/c.notStartedYet'; import You_can_not_navigate_to_other_pages from '@salesforce/label/c.You_can_not_navigate_to_other_pages'; import Initial_batch_processing from '@salesforce/label/c.Initial_batch_processing'; import Finishing_Background_Setup from '@salesforce/label/c.Finishing_Background_Setup'; import Background_Setup_Finished from '@salesforce/label/c.Background_Setup_Finished'; import apex_heap_size_too_large from '@salesforce/label/c.apex_heap_size_too_large'; import Aborted_by_user from '@salesforce/label/c.Aborted_by_user'; import Product from '@salesforce/label/c.Product'; import Variant from '@salesforce/label/c.Variant'; import Account from '@salesforce/label/c.Account'; import Contact from '@salesforce/label/c.Contact'; import Order from '@salesforce/label/c.Order'; import Collection from '@salesforce/label/c.Collection'; import Opportunity from '@salesforce/label/c.Opportunity'; import Location from '@salesforce/label/c.Location'; import Collect from '@salesforce/label/c.Collect'; import Smart_Collection from '@salesforce/label/c.Smart_Collection'; import Inventory from '@salesforce/label/c.Inventory'; import Draft_Order from '@salesforce/label/c.Draft_Order'; import In_Queue from '@salesforce/label/c.In_Queue'; import Not_Started_Yet from '@salesforce/label/c.Not_Started_Yet'; import Completed from '@salesforce/label/c.Completed'; import Shopify_Credentials from '@salesforce/label/c.Shopify_Credentials'; import Notification_will_be_sent_on_below_email from '@salesforce/label/c.Notification_will_be_sent_on_below_email'; //this.label.Aborted_by_user /** * Keeps the percentage text and the progress bar in agreement with the batch * status, so a card can never read "In Progress (100%)". * * Why this is needed: items.status only becomes Completed when the Apex batch * result string contains 'Completed', but dataPercentage is computed separately * as count/totalCount. Once every record is fetched the ratio hits 100% while * the batch job has not reported Completed yet -- so the card showed * "In Progress (100%)". Percentage is therefore capped at 99% until the batch * actually reports Completed. The bar width is always the same number as the * text, so the two can never disagree. * * This mirrors how the page's own overall bar already behaves (see * progressBarController: <100 => inProgress, ===100 => completed). */ function applyProgressBar(items) { // Width the bar stops at while a batch is still running. 99% is visually // indistinguishable from a full bar, which made an in-progress card look // finished -- so the bar is held back to leave a clearly visible gap. const IN_PROGRESS_MAX_BAR = 88; if (items.statusColorClass === 'completed') { items.dataPercentage = 100; items.progressStyle = 'width: 100%;'; return; } if (items.statusColorClass === 'inProgress') { // Text keeps the REAL fetched percentage (capped at 99 so it can never // read "In Progress (100%)"). items.dataPercentage = Math.min(99, items.dataPercentage || 0); // Bar is the same value but never allowed to look full while running. items.progressStyle = 'width: ' + Math.min(IN_PROGRESS_MAX_BAR, items.dataPercentage) + '%;'; return; } items.dataPercentage = 0; items.progressStyle = 'width: 0%;'; } export default class Finished extends NavigationMixin(LightningElement) { StoreLogo = StoreLogo; // DISPLAY-ONLY: current calendar year for the copyright footer. get currentYear() { return new Date().getFullYear(); } // GLOBAL VARIABLES @api storeName = ''; @track isHeapSize = false; // LOCAL VARIABLES @track configObject = {}; @track isModalOpen = false; @track appReviewUrl = ''; @track facebookUrl = ''; @track YouTubeUrl = ''; @track instagramUrl = ''; @track linkedinUrl = ''; @track twitterUrl = ''; @track showErrormessage = Oops_Some_Error_occurred; @track recordFetchMessage = Completed; @track batchConfiguredMessage = 'In Progress'; @track progressClass = notStartedYet; @track hasPersonAccountRecordType = false; @track hasAccountAndContactRecordType = false; @track emailList = []; @track batchProcessingMessage = You_can_not_navigate_to_other_pages; @track isobjectStatusListSecond = false; @track reportObject = {}; upgradeProImg = Resources + '/Resources/Pro.png'; SyncProImg = Resources + '/Resources/SyncPro.png'; SendingMailFalse = image; user1 = user1Image; user2 = user2Image; user3 = user3Image; progressPercent = 0; //Custom Labels @track label = { Close, Final_Page_First_error, for_more_help_contact_us_at, Process_re_again, Configure_Re_Again, Notification_will_be_sent_on_below_email, Thank_you_for_using, Sync_Made_Easy, We_will_send_you_an_email, Currently_Syncing, Batch_Status, Notification_will_be_sent_on_below_emails, Open_Report, Built_with, by_HIC_Global_Solutions, Oops_Some_Error_occurred, Complete, In_Progress, notStartedYet, You_can_not_navigate_to_other_pages, Initial_batch_processing, Finishing_Background_Setup, Background_Setup_Finished, apex_heap_size_too_large, Aborted_by_user, Product, Variant, Account, Contact, Order, Opportunity, Collection, Location, Collect, Smart_Collection, Inventory, Draft_Order, In_Queue, Not_Started_Yet, Completed, Shopify_Credentials }; //THIS VARIABLE IS USED TO COUNT SALESFORCE RECORDS AGAIN AND AGAIN intervalId; // PUTTING ALL THE LOGOS IN AN OBJECT TO SHOW IT ON UI // logo = { // Youtube_sync, // Instagram_Sync, // Twitter_sync, // LinkedIn_Sync, // Heart, // Review_icon, // Newsletter_icon, // Catvideo_icon // }; logo = { Rating }; Youtube_sync = Resources + "/Resources/Youtube_sync.png"; Instagram_Sync = Resources + "/Resources/Instagram_Sync.png"; Twitter_sync = Resources + "/Resources/Twitter_sync.png"; LinkedIn_Sync = Resources + "/Resources/LinkedIn_Sync.png"; Review_icon = Resources + "/Resources/Review_icon.png"; Newsletter_icon = Resources + "/Resources/SMEPRO.png"; Catvideo_icon = Resources + "/Resources/Catvideo_icon.png"; //THIS LIST IS BEING USED SHOW THE RECORDS OF SHOPIFY AND SALESFORCE OBJECT FETCHING FROM BATCH CLASSES @track objectStatusList = [ { priority: 1, checkStatus: false, name: Product, objectCounted: false, countObjectName: 'products', objectName: 'Product2', className: 'BatchToCreateProducts', iconName: 'standard:product', isProductIcon: true, status: Not_Started_Yet, statusColorClass: 'notStartedYet', count: In_Queue, colorClass: 'notStarted', totalCount: 100, dataPercentage: 0, progressStyle: 'width: 0%;' }, { priority: 2, checkStatus: false, name: Variant, objectCounted: false, countObjectName: 'variants', objectName: 'HIC_ShopifySync__Variant__c', className: 'BatchToCreateProducts', iconName: 'standard:product', isVariantIcon: true, status: Not_Started_Yet, statusColorClass: 'notStartedYet', count: In_Queue, colorClass: 'notStarted', totalCount: 100, dataPercentage: 0, progressStyle: 'width: 0%;' }, { priority: 3, checkStatus: false, name: Account, objectCounted: false, countObjectName: 'customers', objectName: 'Account', className: 'FetchAccounts', iconName: 'standard:account', isAccountIcon: true, status: Not_Started_Yet, statusColorClass: 'notStartedYet', count: In_Queue, colorClass: 'notStarted', totalCount: 100, dataPercentage: 0, progressStyle: 'width: 0%;' }, { priority: 4, checkStatus: false, name: Contact, objectCounted: false, countObjectName: 'customers', objectName: 'Contact', className: 'FetchAccounts', iconName: 'standard:contact', isContactIcon: true, status: Not_Started_Yet, statusColorClass: 'notStartedYet', count: In_Queue, colorClass: 'notStarted', totalCount: 100, dataPercentage: 0, progressStyle: 'width: 0%;' }, { priority: 5, checkStatus: false, name: Draft_Order, objectCounted: false, countObjectName: 'draft_orders', objectName: 'Draftorder', className: 'FetchOrders', iconName: 'standard:return_order_line_item', isDraftOrderIcon: true, status: Not_Started_Yet, statusColorClass: 'notStartedYet', count: In_Queue, colorClass: 'notStarted', totalCount: 100, dataPercentage: 0, progressStyle: 'width: 0%;' }, { priority: 6, checkStatus: false, name: Order, objectCounted: false, countObjectName: 'orders', objectName: 'Order', className: 'FetchOrders', iconName: 'standard:orders', isOrderIcon: true, status: Not_Started_Yet, statusColorClass: 'notStartedYet', count: In_Queue, colorClass: 'notStarted', totalCount: 100, dataPercentage: 0, progressStyle: 'width: 0%;' }, { priority: 7, checkStatus: false, name: Opportunity, objectCounted: false, countObjectName: 'orders', objectName: 'Opportunity', className: 'FetchOrders', iconName: 'standard:opportunity', isOpportunityIcon: true, status: Not_Started_Yet, statusColorClass: 'notStartedYet', count: In_Queue, colorClass: 'notStarted', totalCount: 100, dataPercentage: 0, progressStyle: 'width: 0%;' }, { priority: 8, checkStatus: false, name: Collection, objectCounted: false, countObjectName: 'custom_collections', objectName: 'HIC_ShopifySync__Collection__c', className: 'FetchCollections_Batch', iconName: 'standard:product_required', isCollectionIcon: true, status: Not_Started_Yet, statusColorClass: 'notStartedYet', count: In_Queue, colorClass: 'notStarted', totalCount: 100, dataPercentage: 0, progressStyle: 'width: 0%;' }, { priority: 9, checkStatus: false, name: Smart_Collection, objectCounted: false, countObjectName: 'smart_collections', objectName: 'HIC_ShopifySync__Collection__c', className: 'FetchSmartCollection_Batch', iconName: 'standard:collection', isSmartCollectionIcon: true, status: Not_Started_Yet, statusColorClass: 'notStartedYet', count: In_Queue, colorClass: 'notStarted', totalCount: 100, dataPercentage: 0, progressStyle: 'width: 0%;' }, { priority: 10, checkStatus: false, name: Collect, objectCounted: false, countObjectName: 'collects', objectName: 'HIC_ShopifySync__Collect__c', className: 'FetchCollects_Batch', iconName: 'standard:collection', isCollectIcon: true, status: Not_Started_Yet, statusColorClass: 'notStartedYet', count: In_Queue, colorClass: 'notStarted', totalCount: 100, dataPercentage: 0, progressStyle: 'width: 0%;' }, { priority: 11, checkStatus: false, name: Location, objectCounted: false, countObjectName: 'locations', objectName: 'HIC_ShopifySync__Location__c', className: 'FetchLocations_Batch', iconName: 'standard:location', isLocationIcon: true, status: Not_Started_Yet, statusColorClass: 'notStartedYet', count: In_Queue, colorClass: 'notStarted', totalCount: 100, dataPercentage: 0, progressStyle: 'width: 0%;' } ]; @track objectStatusListSecond = [ { priority: 1, checkStatus: false, name: Inventory, objectCounted: false, countObjectName: 'inventory_levels', objectName: 'HIC_ShopifySync__Inventory__c', className: 'FetchInventoryItems', iconName: 'standard:product', isInventoryIcon: true, status: Not_Started_Yet, statusColorClass: 'notStartedYet', count: In_Queue, colorClass: 'notStarted', totalCount: 100, dataPercentage: 0, progressStyle: 'width: 0%;' }, ]; //connected call back connectedCallback() { console.log('SYNC MADE EASY: Finished Connected Callback : ' + this.storeName); this.getConfigurations(); this.getUrl(); this.isBatchProcessing(true); this.getErrorMailListMethod(); } //This method is used to find if Salesforce org have Person Account enabled or not @wire(getIsPerson) person({ data, error }) { console.log('SYNC MADE EASY: Finished => Fetching Person Account'); if (data) { getGeneral({ store: this.storeName }).then((result) => { let configObj = JSON.parse(result); var accountAndContact = configObj.HIC_ShopifySync__Account_Contact__c; var personAccount = configObj.HIC_ShopifySync__Person_Account__c; if (accountAndContact == true && personAccount == false) { this.hasAccountAndContactRecordType = true; } else if (accountAndContact == false && personAccount == true) { this.hasPersonAccountRecordType = true; } }).catch((error) => { //Error Occured }) } else if (error) { //Error Occured } } @wire(getReports) getAllReports({ data, error }) { console.log('SYNC MADE EASY: Finished => Fetching Reports'); if (data) { this.reportObject = data; console.log('this is Report Object 06-05-2025>>>' + JSON.stringify(this.reportObject)); } else if (error) { console.log('SYNC MADE EASY: Finished => Fetching Report Error ' + error); } } isBatchProcessing(isProcessing) { const batchStatusEvent = new CustomEvent('checkbatchstatus', { detail: isProcessing }); this.dispatchEvent(batchStatusEvent); } //THIS METHOD IS USED TO FETHC THE STORE CONFIGURATION USING STORE NAME GETTING FROM THE HOME COMPONENT async getConfigurations() { console.log('SYNC MADE EASY: Finished => Fetching Store Details'); try { const result = await getConfigrationForDynamicRow({ store: this.storeName }); if (result) { this.configObject = JSON.parse(result); let objectList = this.objectStatusList; let objectListSecond = this.objectStatusListSecond; this.objectStatusList = objectList.map((obj) => { if (this.configObject.HIC_ShopifySync__Product_Sync__c === true && (obj.objectName === 'Product2' || obj.objectName === 'HIC_ShopifySync__Variant__c')) { obj.checkStatus = true; } if (this.configObject.HIC_ShopifySync__Person_Account__c === false && this.configObject.HIC_ShopifySync__Account_Contact__c === true && this.configObject.HIC_ShopifySync__Customer_Sync__c === true && (obj.objectName === 'Contact' || obj.objectName === 'Account')) { obj.checkStatus = true; } if (this.configObject.HIC_ShopifySync__Person_Account__c === true && this.configObject.HIC_ShopifySync__Account_Contact__c === false && obj.objectName === 'Contact') { obj.checkStatus = false; } if (this.configObject.HIC_ShopifySync__Person_Account__c === true && this.configObject.HIC_ShopifySync__Account_Contact__c === false && obj.objectName === 'Account') { obj.name = 'Person Account'; obj.checkStatus = true; } if (this.configObject.HIC_ShopifySync__Default_Account__c === true && obj.objectName === 'Account') { obj.checkStatus = false; } if (this.configObject.HIC_ShopifySync__Order__c === true && obj.objectName === 'Order') { obj.checkStatus = true; } if (this.configObject.HIC_ShopifySync__Collection_Sync__c === true && obj.objectName === 'HIC_ShopifySync__Collect__c') { obj.checkStatus = true; } if (this.configObject.HIC_ShopifySync__Inventory_Location__c === true && obj.objectName === 'HIC_ShopifySync__Location__c') { obj.checkStatus = true; } if ((this.configObject.HIC_ShopifySync__Enable_Draft_Order__c === true || this.configObject.HIC_ShopifySync__Enable_Opportunity_for_SDO__c == true) && obj.objectName === 'Draftorder') { obj.checkStatus = true; } if ((this.configObject.HIC_ShopifySync__Opportunity__c === true || this.configObject.HIC_ShopifySync__Enable_Opportunity_for_SDO__c === true) && obj.objectName === 'Opportunity') { obj.checkStatus = true; } if (this.configObject.HIC_ShopifySync__Collection_Sync__c === true && (obj.objectName === 'HIC_ShopifySync__Collection__c')) { obj.checkStatus = true; } obj.showCard = obj.checkStatus; if (obj.objectName === 'Draftorder') { obj.showCard = obj.checkStatus && this.configObject.HIC_ShopifySync__Enable_Draft_Order__c === true; } return obj; }); this.objectStatusListSecond = objectListSecond.map((obj) => { if (this.configObject.HIC_ShopifySync__Inventory_Location__c === true && obj.objectName === 'HIC_ShopifySync__Inventory__c') { obj.checkStatus = true; } if (this.configObject.HIC_ShopifySync__Collection_Sync__c === true && (obj.objectName === 'HIC_ShopifySync__Collection__c')) { obj.checkStatus = true; } obj.showCard = obj.checkStatus; return obj; }); if (this.configObject.HIC_ShopifySync__Inventory_Location__c) { this.isobjectStatusListSecond = true; } } /** CALLING THE MEHTOD TO COUNT THE NUMBER OF RECORDS ON SHOPIFY SIDE */ await this.shopifyRecordCount(); /** CALLING THE MEHTOD TO COUNT THE NUMBER OF RECORDS IN SALESFORCE, RUNNING WHILE THE BATCH IS PROCESSING */ this.stopCounter(); } catch (error) { console.error('Error in getConfigurations:', error); } } /** * DISCONNECTED CALLBACK */ disconnectedCallback() { // clearInterval(this.intervalId); clearTimeout(this.intervalId); } /** * THIS METHOD IS USED TO CLEAR THE INTERVAL VARIABLE IF ALL THE BATCHES ARE COMPLETED SO THAT REAL TIME BATCH STATUS GETTING PROCESS IS STOPPED * */ async stopCounter() { let stopTimer = true; let firstBatchCompleted = true; CountSalesforce: for (let items of this.objectStatusList) { if (items.status !== this.label.Completed && items.checkStatus === true) { firstBatchCompleted = false; stopTimer = false; try { if (items.count == this.label.In_Queue) { items.count = 0; } items.status = this.label.In_Progress; items.colorClass = 'started'; items.statusColorClass = 'inProgress'; applyProgressBar(items); const result = await this.salesforceRecordCount(items); this.progressBarController(); break CountSalesforce; } catch (error) { console.log('SYNC MADE EASY: Finished ' + error); } } } if (firstBatchCompleted) { this.batchProcessingMessage = this.label.Initial_batch_processing; this.batchConfiguredMessage = this.label.Finishing_Background_Setup; // NEED TO CHANGE THE MESSAGE OF CountSalesforceRecords: for (let items of this.objectStatusListSecond) { if (items.status !== this.label.Completed && items.checkStatus === true) { stopTimer = false; try { if (items.count == this.label.In_Queue) { items.count = 0; } items.status = this.label.In_Progress; items.colorClass = 'started'; items.statusColorClass = 'inProgress'; applyProgressBar(items); const result = await this.salesforceRecordCount(items); break CountSalesforceRecords; } catch (error) { //Error Occured } } } } if (stopTimer) { this.batchConfiguredMessage = this.label.Background_Setup_Finished; const batchCompletedEvent = new CustomEvent('batchcompleted', { detail: this.label.Shopify_Credentials }); this.dispatchEvent(batchCompletedEvent); } else { this.stopCounter(); } } /** THIS METHOD IS USED TO COUNT THE NUMBER OF RECORDS IN SALESFORCE AND GET THE REAL TIME BATCH STATUS OF EVERY OBJECT */ async salesforceRecordCount(items) { return new Promise((resolve, reject) => { console.log('SYNC MADE EASY: Finished => Checking Batch Details of ' + items.objectName); CheckingBatchDetails({ ObjectName: items.objectName, ApexClassName: items.className, store: this.storeName }).then((result) => { console.log('SYNC MADE EASY: Finished => Checking Batch Detail Result ' + result); console.log('Item object Name : ' + items.objectName); console.log('item result : ' + result); //CHECKING IF THE BATCH IS ABORTED. if (result !== null && result.includes('Aborted')) { this.openModal(); let Errormessage = (result.replace("Aborted", "")).trim(); if (Errormessage.toLowerCase().includes(this.label.apex_heap_size_too_large)) { this.isHeapSize = true; this.handlesyncShopify(); } else if (Errormessage.includes("-job") && Errormessage.includes("aborted")) { Errormessage = this.label.Aborted_by_user; this.showErrormessage = Errormessage; this.isBatchProcessing(false); } // clearInterval(this.intervalId); clearTimeout(this.intervalId); items.status = this.label.Not_Started_Yet; return; } items.count = Number(result.replace('Completed', '')); //CHECKING IF THE BATCH IS COMPLETED. if (result.includes('Completed')) { if ((items.count === items.totalCount || items.count > items.totalCount)) { items.status = this.label.Completed; items.colorClass = 'complete'; items.statusColorClass = 'completed'; applyProgressBar(items); items.count = items.totalCount; console.log('Item Count equal totalCount ' + items.count); console.log('Item Total Count ' + items.totalCount); } else if (items.count < items.totalCount && result.includes('Completed')) { // items.totalCount = items.count; items.status = this.label.Completed; items.colorClass = 'complete'; items.statusColorClass = 'completed'; applyProgressBar(items); console.log('Item Count less than totalCount ' + items.count); console.log('Item Total Count ' + items.totalCount); } else { // Not completed } } else if (items.totalCount < items.count) { items.count = items.totalCount; console.log('Item Count ' + items.count); console.log('Item Total Count ' + items.totalCount); } /** * Calculating the percentage of the records fetched from background */ if (items.totalCount == 0 || items.objectName == 'HIC_ShopifySync__Inventory__c') { items.dataPercentage = 100; } else { console.log('Item Count ' + items.count); console.log('Item Total Count ' + items.totalCount); items.dataPercentage = Math.floor((items.count / items.totalCount) * 100); console.log('Item Data Percentage ' + items.dataPercentage); } applyProgressBar(items); }).catch((error) => { //Error Occured }); this.intervalId = setTimeout(() => { resolve('Success!'); }, 5000); }); } async shopifyRecordCount() { const promises = []; // ---- First list ---- for (let items of this.objectStatusList) { if (items.status !== this.label.Completed && items.checkStatus === true) { console.log('SYNC MADE EASY: Finished => Fetching Number of Shopify Records'); const p = getShopifyRecordCounts({ storeName: this.storeName, objectName: items.countObjectName }) .then((result) => { if (result !== 'Error!') { console.log('Shopify Count Result ' + result); console.log('Object Name : ', items.objectName); console.log(' items.countObjectName :', items.countObjectName); const shopifyCount = Number(JSON.parse(result).count); // RAW Shopify count (source of truth) console.log('Shopify Count ' + shopifyCount); items.shopifyTotalCount = shopifyCount; items.totalCount = shopifyCount; // Recalculate dataPercentage now that we have the real totalCount // This fixes the race condition where percentage was calculated // against the stale default totalCount of 100 if (typeof items.count === 'number') { items.dataPercentage = Math.min( 100, Math.floor((items.count / shopifyCount) * 100) ); } applyProgressBar(items); // Force UI refresh with corrected percentages this.objectStatusList = [...this.objectStatusList]; this.progressBarController(); } }) .catch((error) => { console.error('Shopify count error:', error); }); promises.push(p); } } // ---- Second list ---- for (let items of this.objectStatusListSecond) { if (items.status !== this.label.Completed && items.checkStatus === true) { const p = getShopifyRecordCounts({ storeName: this.storeName, objectName: items.countObjectName }) .then((result) => { if (result !== 'Error!') { console.log('Shopify Count Result for Inventory Levels ' + result); const shopifyCount = Number(JSON.parse(result).count); items.shopifyTotalCount = shopifyCount; items.totalCount = shopifyCount; // Recalculate dataPercentage now that we have the real totalCount if (typeof items.count === 'number') { items.dataPercentage = Math.min( 100, Math.floor((items.count / items.count) * 100) ); } applyProgressBar(items); // Force UI refresh with corrected percentages this.objectStatusListSecond = [...this.objectStatusListSecond]; } }) .catch((error) => { console.error('Shopify count error:', error); }); promises.push(p); } } // Wait for all Shopify counts to complete await Promise.all(promises); // Final recalculation of progress bar after all counts are in this.progressBarController(); } /** * USED TO CALCULATE THE PERCETAGE OF RECORDS FETCHED FROM THE SHOPIFY AND UPDATE THE MESSAGES ACCORDINGLY */ progressBarController() { let salesforceCount = 0; let shopifyCount = 0; let draftCount = 0; // 1️ Raw totals for (let items of this.objectStatusList) { if (items.checkStatus === true) { if (typeof items.count === 'number') { salesforceCount += items.count; if (items.objectName == 'Draftorder' && !this.configObject.HIC_ShopifySync__Enable_Draft_Order__c && this.configObject.HIC_ShopifySync__Draft_Order_Sync__c) { draftCount += items.count; } } if (items.objectName == 'Opportunity' && this.configObject.HIC_ShopifySync__Opportunity__c) { shopifyCount += (items.shopifyTotalCount || 0); } if (items.objectName == 'Draftorder') { if (this.configObject.HIC_ShopifySync__Enable_Opportunity_for_SDO__c && this.configObject.HIC_ShopifySync__Enable_Draft_Order__c) { shopifyCount += ((items.shopifyTotalCount * 2) || 0); } else if (this.configObject.HIC_ShopifySync__Enable_Opportunity_for_SDO__c || this.configObject.HIC_ShopifySync__Enable_Draft_Order__c) { shopifyCount += (items.shopifyTotalCount || 0); } } else if (items.objectName !== 'Opportunity') { shopifyCount += (items.shopifyTotalCount || 0); } } } // 2️ Progress % if (shopifyCount === 0) { this.progressPercent = 0; } else { salesforceCount = salesforceCount - draftCount; console.log('salesforce count-->', salesforceCount); console.log('shopifyCount-->', shopifyCount); this.progressPercent = Math.floor( (salesforceCount / shopifyCount) * 100 ); if (this.progressPercent > 100) { this.progressPercent = 100; } } // 3️ Status if (this.progressPercent < 2) { this.progressClass = 'errors'; } else if (this.progressPercent <= 30) { this.progressClass = 'notStartedYet'; } else if (this.progressPercent < 100) { this.progressClass = 'inProgress'; } else { this.progressClass = 'completed'; this.recordFetchMessage = this.label.Completed; this.batchConfiguredMessage = this.label.Background_Setup_Finished; } // 4️ Opportunity SUM (Order + Draft Order) let orderTotal = 0; let draftOrderTotal = 0; for (let item of this.objectStatusList) { if (item.countObjectName === 'orders' && this.configObject.HIC_ShopifySync__Order_Sync__c) { orderTotal = item.shopifyTotalCount || 0; } if (item.countObjectName === 'draft_orders') { draftOrderTotal = item.shopifyTotalCount || 0; } } for (let item of this.objectStatusList) { if (item.objectName === 'Opportunity' && this.configObject.HIC_ShopifySync__Opportunity__c && this.configObject.HIC_ShopifySync__Enable_Opportunity_for_SDO__c) { item.totalCount = orderTotal + draftOrderTotal; } if (item.objectName === 'Opportunity' && !this.configObject.HIC_ShopifySync__Opportunity__c && this.configObject.HIC_ShopifySync__Enable_Opportunity_for_SDO__c) { item.totalCount = draftOrderTotal; } if (item.objectName === 'Opportunity' && this.configObject.HIC_ShopifySync__Opportunity__c && !this.configObject.HIC_ShopifySync__Enable_Opportunity_for_SDO__c) { item.totalCount = orderTotal; } if (item.objectName === 'Opportunity' && !this.configObject.HIC_ShopifySync__Order_Sync__c && this.configObject.HIC_ShopifySync__Enable_Opportunity_for_SDO__c) { item.totalCount = draftOrderTotal; } } this.objectStatusList = [...this.objectStatusList]; } /** * USED TO UPDATED THE CLASS OF PROGRESS PATH TO CHANGE COLOR */ get progressClass() { if (this.progressPercent <= 30) { return 'notStartedProgress'; } else if (this.progressPercent < 100 && this.progressPercent > 30) { return 'startedProgress'; } else if (this.progressPercent < 2) { return 'errorProgress'; } else { return 'completeProgress'; } } /** * METHOD IS USED TO OPEN THE ERROR MESSAGE MODAL IF ANY ERROR OCCURED IN BATCH */ openModal() { this.isModalOpen = true; } /** * METHOD IS USED TO CLOSE THE ERROR MESSAGE MODAL WHICH WAS SHOWING THE ERROR MESSAGE OF BATCH */ closeModal() { this.isModalOpen = false; } /** * USED TO RE-SYNC THE BATCH IS ANY ERROR OCCURED IN BATCH CLASS. THIS METHOD STARTS THE BATCH AGAIN. */ handlesyncShopify() { console.log('SYNC MADE EASY: Finished => Re-Sync Shopify '); updateconfigurationpbatchprocessingfield({ store: this.storeName, isHeapSize: this.isHeapSize }).then((result) => { syncShopify({ store: this.storeName }) .then((result) => { this.closeModal(); for (let items of this.objectStatusList) { items.status = this.label.Not_Started_Yet; items.statusColorClass = 'notStartedYet'; applyProgressBar(items); items.count = this.label.In_Queue; items.colorClass = 'notStarted'; } // this.objectStatus(); this.stopCounter(); }).catch((error) => { console.error('Error:', error); }); }).catch((error) => { //Error Occured }); } /** * METHOD IS USED TO OPEN THE CREDENTIAL PAGE TO EDIT STORE DETAILS IF ANY ERROR OCCURED IN BATCH, CALLED FROM THE BUTTON ON UI */ handleUpdateConfiguration() { console.log('SYNC MADE EASY: Finished => Re-Start the Configuration with Manual Mode'); // FIRST: Turn OFF auto configuration (uncheck B2B Store checkbox) updateAutoConfiguration({ storeName: this.storeName, isAuto: false // false = manual mode }) .then(() => { console.log('>>> Auto Configuration turned OFF for store: ' + this.storeName); // SECOND: Update batch processing field return updateconfigurationpbatchprocessingfield({ store: this.storeName, isHeapSize: false }); }) .then(() => { // THIRD: Close modal and dispatch event to navigate to credentials this.closeModal(); // Dispatch event to parent (Home component) to navigate to Shopify Credentials const selectStore = new CustomEvent('save', { detail: this.label.Shopify_Credentials }); this.dispatchEvent(selectStore); // ALSO dispatch event to turn off auto-config in parent component const autoConfigEvent = new CustomEvent('autoconfigchange', { detail: false, // false = manual mode bubbles: true, composed: true }); this.dispatchEvent(autoConfigEvent); }) .catch((error) => { console.error('>>> Error turning off auto configuration:', error); // Still navigate even if update fails this.closeModal(); const selectStore = new CustomEvent('save', { detail: this.label.Shopify_Credentials }); this.dispatchEvent(selectStore); }); } /** * THIS METHOD IS USED TO FETCH ALL THE SOCIAL SITE URLS AND SHOW ON COMPONENT */ getUrl() { console.log('SYNC MADE EASY: Finished => Fetch Important Urls '); getWriteReviewURL().then((result) => { let urlMapping = JSON.parse(result).map((obj) => { if (obj.name == 'Instagram') { this.instagramUrl = obj.Url; } if (obj.name == 'Twitter') { this.twitterUrl = obj.Url; } if (obj.name == 'AppWriteReviewURL') { this.appReviewUrl = obj.Url; } if (obj.name == 'Facebook') { this.facebookUrl = obj.Url; } if (obj.name == 'Facebook') { this.YouTubeUrl = obj.Url; } if (obj.name == 'Linkedin') { this.linkedinUrl = obj.Url; } }); }).catch((error) => { //Error Occured }); } //This method Gets list of Email to send email notifications after Batch process complete getErrorMailListMethod() { console.log('SYNC MADE EASY: Finished => Sending Error Mail'); getErrorMailList().then((result) => { if (result) { this.emailList = []; this.emailList = JSON.parse(result).map((email) => { return { value: email.Name }; }); } }).catch((error) => { //Error Occured }) } // DISPLAY-ONLY: computes the SVG ring's stroke-dashoffset from the existing // progressPercent value. Purely presentational — no functional impact. get ringDashoffsetStyle() { const circumference = 408; const pct = Math.min(100, Math.max(0, this.progressPercent || 0)); const offset = circumference - (circumference * pct / 100); return `stroke-dashoffset: ${offset};`; } get notificationText() { return this.emailList.length === 1 ? Notification_will_be_sent_on_below_email : this.label.Notification_will_be_sent_on_below_emails; } // Method to open Report openReport(event) { const objName = event.target.dataset.id; console.log('SYNC MADE EASY: Finished => OPEN REPORT ' + objName); let reportID = ''; if (objName != null && objName != '' && objName != undefined) { if ((this.configObject.HIC_ShopifySync__Person_Account__c === true && this.configObject.HIC_ShopifySync__Account_Contact__c === false && objName.toUpperCase() === 'ACCOUNT') && this.reportObject.PersonAccount) { reportID = this.reportObject.PersonAccount; this.navigateToReport(reportID); } else if ((objName.toUpperCase() == 'ACCOUNT') && this.reportObject.BusinessAccount) { reportID = this.reportObject.BusinessAccount; this.navigateToReport(reportID); } else if ((objName.toUpperCase() === 'CONTACT') && this.reportObject.Contact) { reportID = this.reportObject.Contact; this.navigateToReport(reportID); } else if ((objName.toUpperCase() === 'PRODUCT2') && this.reportObject.Product) { reportID = this.reportObject.Product; this.navigateToReport(reportID); } else if ((objName.toUpperCase() === 'HIC_SHOPIFYSYNC__VARIANT__C') && this.reportObject.Variant) { reportID = this.reportObject.Variant; this.navigateToReport(reportID); } else if ((objName.toUpperCase() === 'ORDER') && this.reportObject.Order) { reportID = this.reportObject.Order; this.navigateToReport(reportID); } else if ((objName.toUpperCase() === 'DRAFTORDER') && this.reportObject.DraftOrders) { reportID = this.reportObject.DraftOrders; this.navigateToReport(reportID); } else if ((objName.toUpperCase() === 'OPPORTUNITY') && this.reportObject.Opportunity) { reportID = this.reportObject.Opportunity; this.navigateToReport(reportID); } else if ((objName.toUpperCase() === 'HIC_SHOPIFYSYNC__COLLECTION__C') && this.reportObject.Collection) { reportID = this.reportObject.Collection; this.navigateToReport(reportID); } else if ((objName.toUpperCase() === 'HIC_SHOPIFYSYNC__COLLECT__C') && this.reportObject.Collect) { reportID = this.reportObject.Collect; this.navigateToReport(reportID); } else if ((objName.toUpperCase() === 'HIC_SHOPIFYSYNC__LOCATION__C') && this.reportObject.Location) { reportID = this.reportObject.Location; this.navigateToReport(reportID); } else if ((objName.toUpperCase() === 'HIC_SHOPIFYSYNC__INVENTORY__C') && this.reportObject.Inventory) { reportID = this.reportObject.Inventory; this.navigateToReport(reportID); } else { console.log('SYNC MADE EASY: Finished => No Report Found'); } } } // Method to show report navigateToReport(reportId) { this[NavigationMixin.GenerateUrl]({ type: 'standard__recordPage', attributes: { recordId: reportId, objectApiName: 'Report', actionName: 'view' }, state: { fv0: this.storeName, }, }).then((url) => { window.open(url); }); } handleAbortClick() { abortBatch().then((result) => { console.log('Batch Aborted Sucessfully'); console.log('SYNC MADE EASY: Finished => Re-Start the Configuration '); updateconfigurationpbatchprocessingfield({ store: this.storeName, isHeapSize: false }).then((result) => { //this.closeModal(); const selectStore = new CustomEvent('save', { detail: this.label.Shopify_Credentials }); this.dispatchEvent(selectStore); }).catch((error) => { //Error Occured }); this.isBatchProcessing(false); }).catch((error) => { //Error Occured }) } }