diff --git a/.gitignore b/.gitignore index 56824e890..59c3652fb 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,5 @@ documentation.json # Sentry Config File .sentryclirc + +commits.csv diff --git a/deploy_dump.sh b/deploy_dump.sh new file mode 100644 index 000000000..784149a5a --- /dev/null +++ b/deploy_dump.sh @@ -0,0 +1,11 @@ +if [ -z "$1" ]; then + echo "Usage: sh $0 '2024-12-09'" + exit 1 +fi + +base_url="https://github.com/fylein/fyle-integrations-app/commit" +branch_name=$(git rev-parse --abbrev-ref HEAD) + +git log --since="$1" --pretty=format:"$base_url/%H,%an,%ad,%s,$branch_name,integrations-app" > commits.csv + +open commits.csv diff --git a/src/app/branding/c1-branding-config.ts b/src/app/branding/c1-branding-config.ts index 86ac71d3a..9b14d4e90 100644 --- a/src/app/branding/c1-branding-config.ts +++ b/src/app/branding/c1-branding-config.ts @@ -128,9 +128,7 @@ export const c1KbArticles: KbArticle[string] = { IMPORT_SETTING: `${brandingConfig.helpArticleDomain}/en/articles/9082146-configure-the-capital-one-sage-intacct-integration#h_78e1747002`, EXPORT_SETTING: `${brandingConfig.helpArticleDomain}/en/articles/9082146-configure-the-capital-one-sage-intacct-integration#h_eebe5df4b7`, ADVANCED_SETTING: `${brandingConfig.helpArticleDomain}/en/articles/9082146-configure-the-capital-one-sage-intacct-integration#h_498f2acc61`, - LANDING: `${brandingConfig.helpArticleDomain}/en/articles/9082146-configure-the-capital-one-sage-intacct-integration`, CONNECTOR: `${brandingConfig.helpArticleDomain}/en/articles/9081356-generate-credentials-to-connect-with-sage-intacct`, - SKIP_EXPORT: `${brandingConfig.helpArticleDomain}/en/articles/9082146-configure-the-capital-one-sage-intacct-integration`, HELPER_ARTICLE: `${brandingConfig.helpArticleDomain}/en/articles/7882821-how-to-skip-exporting-specific-expenses-from-fyle-to-sage-intacct` } } diff --git a/src/app/branding/c1-contents-config.ts b/src/app/branding/c1-contents-config.ts index a9d9ddb30..b24efc370 100644 --- a/src/app/branding/c1-contents-config.ts +++ b/src/app/branding/c1-contents-config.ts @@ -254,7 +254,10 @@ export const c1Contents = { accountingPeriodSubLabel: 'If the accounting period is closed, the expenses will be exported with a date stamp for the first day of the current open accounting period.', autoCreateVendorsSubLabel: 'Automatically create a new contact in Xero if an added merchant doesn\'t have a corresponding match.', customPreferencesLabel: 'Other preferences', - customPreferencesSubLabel: 'Create new records in Xero if no contacts found or the accounting period is closed.' + customPreferencesSubLabel: 'Create new records in Xero if no contacts found or the accounting period is closed.', + memoStructureLabel: 'Set the line-item description field in Xero', + memoStructureSubLabel: 'Choose from a list of available data points that you\'d like to export to the description field in Xero.', + customizeSectionSubLabel: 'Customize the data that you\'d like to export from Expense Management to Xero by choosing which data points need to be exported.' } } }, diff --git a/src/app/branding/fyle-branding-config.ts b/src/app/branding/fyle-branding-config.ts index c65ddfde4..609ce70d1 100644 --- a/src/app/branding/fyle-branding-config.ts +++ b/src/app/branding/fyle-branding-config.ts @@ -67,7 +67,7 @@ export const fyleKbArticles: KbArticle[string] = { SAGE300: `${brandingConfig.helpArticleDomain}/en/articles/8948413-how-to-set-up-the-fyle-sage-300-cre-integration`, BUSINESS_CENTRAL: `${brandingConfig.helpArticleDomain}/en/articles/8911018-how-to-configure-the-fyle-dynamics-365-business-central-integration`, XERO: `${brandingConfig.helpArticleDomain}/en/articles/6721333-how-to-set-up-the-fyle-xero-integration`, - QBD_DIRECT: `${brandingConfig.helpArticleDomain}/en/collections/215867-integrations-with-fyle#quickbooks-desktop` + QBD_DIRECT: `${brandingConfig.helpArticleDomain}/en/articles/10259583-quickbooks-desktop-integration-beta` }, onboardingArticles: { INTACCT: { @@ -126,12 +126,10 @@ export const fyleKbArticles: KbArticle[string] = { ADVANCED_SETTING: `${brandingConfig.helpArticleDomain}/en/articles/6721333-how-to-set-up-the-fyle-xero-integration#h_d95b791edd` }, QBD_DIRECT: { - IMPORT_SETTING: `${brandingConfig.helpArticleDomain}/en/articles/8394683-how-to-configure-the-fyle-sage-intacct-integration#h_85f929716c`, - EXPORT_SETTING: `${brandingConfig.helpArticleDomain}/en/articles/8394683-how-to-configure-the-fyle-sage-intacct-integration#h_6492c5038d`, - ADVANCED_SETTING: `${brandingConfig.helpArticleDomain}/en/articles/8394683-how-to-configure-the-fyle-sage-intacct-integration#h_3f6718633c`, - LANDING: `${brandingConfig.helpArticleDomain}/en/articles/8394683-how-to-configure-the-fyle-sage-intacct-integration`, - CONNECTOR: `${brandingConfig.helpArticleDomain}/en/articles/8394683-how-to-configure-the-fyle-sage-intacct-integration#h_38e0c9bea6`, - SKIP_EXPORT: `${brandingConfig.helpArticleDomain}/en/articles/7882821-how-to-skip-exporting-specific-expenses-from-fyle-to-sage-intacct`, + IMPORT_SETTING: `${brandingConfig.helpArticleDomain}/en/articles/10259583-quickbooks-desktop-integration-beta#h_a170c7d562`, + EXPORT_SETTING: `${brandingConfig.helpArticleDomain}/en/articles/10259583-quickbooks-desktop-integration-beta#h_1366df4107`, + ADVANCED_SETTING: `${brandingConfig.helpArticleDomain}/en/articles/10259583-quickbooks-desktop-integration-beta#h_b3850646c0`, + CONNECTOR: `${brandingConfig.helpArticleDomain}/en/articles/10259583-quickbooks-desktop-integration-beta#h_d3cc42849a`, HELPER_ARTICLE: `${brandingConfig.helpArticleDomain}/en/articles/7882821-how-to-skip-exporting-specific-expenses-from-fyle-to-sage-intacct` } } diff --git a/src/app/branding/fyle-contents-config.ts b/src/app/branding/fyle-contents-config.ts index 53b3f8f46..16d1977ca 100644 --- a/src/app/branding/fyle-contents-config.ts +++ b/src/app/branding/fyle-contents-config.ts @@ -250,6 +250,7 @@ export const fyleContents = { topLevelMemoStructureSubLabel: 'Select the datapoints you\'d like to export to Xero’s top-level memo field when exporting expenses from Fyle.', memoStructureLabel: 'Customize the Line-Item Level Memo Field', memoStructureSubLabel: 'Select the datapoints you\'d like to export to Xero\’s line-item level memo field when exporting expenses from Fyle.', + customizeSectionSubLabel: 'In this section, you can customize the data that you\'d like to export from ' + brandingConfig.brandName + ' to Xero. You can choose what data points need to be exported and what shouldn\'t be.', frequencySubLabel: 'Set a frequency based on how often you want your expenses in Fyle to be exported to Xero.', customPreferencesLabel: 'Other Preferences', customPreferencesSubLabel: 'Based on your preference, you can choose whether you want to create any new records in Xero from ' + brandingConfig.brandName + '. (when there is no employee record found, or when the accounting period is closed)', diff --git a/src/app/core/models/branding/content-configuration.model.ts b/src/app/core/models/branding/content-configuration.model.ts index 88af007c8..0d109e4bf 100644 --- a/src/app/core/models/branding/content-configuration.model.ts +++ b/src/app/core/models/branding/content-configuration.model.ts @@ -248,6 +248,9 @@ export type ContentConfiguration = { scheduleSubLabel: string; accountingPeriodSubLabel: string; autoCreateVendorsSubLabel: string; + memoStructureLabel: string; + memoStructureSubLabel: string; + customizeSectionSubLabel: string; frequencySubLabel: string; } }, diff --git a/src/app/core/models/branding/kb-article.model.ts b/src/app/core/models/branding/kb-article.model.ts index 4d5f0f8a4..d7c1c2418 100644 --- a/src/app/core/models/branding/kb-article.model.ts +++ b/src/app/core/models/branding/kb-article.model.ts @@ -17,9 +17,7 @@ export type KbArticle = { IMPORT_SETTING: string; EXPORT_SETTING: string; ADVANCED_SETTING: string; - LANDING: string; CONNECTOR: string; - SKIP_EXPORT: string; HELPER_ARTICLE: string; }, INTACCT: { diff --git a/src/app/core/models/common/advanced-settings.model.ts b/src/app/core/models/common/advanced-settings.model.ts index 2fc4a360d..735a4d3f1 100644 --- a/src/app/core/models/common/advanced-settings.model.ts +++ b/src/app/core/models/common/advanced-settings.model.ts @@ -1,9 +1,10 @@ import { FormControl, FormGroup } from "@angular/forms"; -import { JoinOption, Operator } from "../enum/enum.model"; +import { AppName, JoinOption, Operator } from "../enum/enum.model"; import { environment } from "src/environments/environment"; import { ExportSettingGet } from "../intacct/intacct-configuration/export-settings.model"; import { QBOExportSettingGet } from "../qbo/qbo-configuration/qbo-export-setting.model"; import { NetSuiteExportSettingGet } from "../netsuite/netsuite-configuration/netsuite-export-setting.model"; +import { IntacctConfiguration } from "../db/configuration.model"; export type EmailOption = { email: string; @@ -75,17 +76,19 @@ export class AdvancedSettingsModel { return ['employee_email', 'employee_name', 'merchant', 'purpose', 'category', 'spent_on', 'report_number', 'expense_link', 'card_number']; } - static getMemoOptions(exportSettings: ExportSettingGet | NetSuiteExportSettingGet | QBOExportSettingGet, appName: string): string[] { + static getMemoOptions(exportSettings: IntacctConfiguration | ExportSettingGet | NetSuiteExportSettingGet | QBOExportSettingGet, appName: string): string[] { const defaultOptions = this.getDefaultMemoOptions(); let cccExportType: string | undefined; // Handle both configurations and configuration properties - if ('configurations' in exportSettings) { + if (appName === AppName.INTACCT) { + cccExportType = (exportSettings as IntacctConfiguration).corporate_credit_card_expenses_object ?? undefined; + } else if ('configurations' in exportSettings) { cccExportType = exportSettings.configurations?.corporate_credit_card_expenses_object ?? undefined; } else if ('workspace_general_settings' in exportSettings) { cccExportType = exportSettings.workspace_general_settings?.corporate_credit_card_expenses_object ?? undefined; } // Filter out options based on cccExportType and appName - if (cccExportType && ['netsuite', 'qbo', 'sage intacct'].includes(appName.toLowerCase())) { + if (cccExportType && ['netsuite', 'quickbooks online', 'sage intacct'].includes(appName.toLowerCase())) { return defaultOptions; // Allow all options including 'card_number' } return defaultOptions.filter(option => option !== 'card_number'); // Omit 'card_number' for other apps diff --git a/src/app/integrations/intacct/intacct-shared/intacct-advanced-settings/intacct-advanced-settings.component.ts b/src/app/integrations/intacct/intacct-shared/intacct-advanced-settings/intacct-advanced-settings.component.ts index 761b0691a..3377486ac 100644 --- a/src/app/integrations/intacct/intacct-shared/intacct-advanced-settings/intacct-advanced-settings.component.ts +++ b/src/app/integrations/intacct/intacct-shared/intacct-advanced-settings/intacct-advanced-settings.component.ts @@ -93,7 +93,7 @@ export class IntacctAdvancedSettingsComponent implements OnInit { private sessionStartTime = new Date(); - defaultMemoFields: string[] = ['employee_email', 'merchant', 'purpose', 'category', 'spent_on', 'report_number', 'expense_link']; + defaultMemoFields: string[] = AdvancedSettingsModel.getDefaultMemoOptions(); paymentSyncOptions: AdvancedSettingFormOption[] = [ { @@ -313,6 +313,7 @@ export class IntacctAdvancedSettingsComponent implements OnInit { if (this.advancedSettings.workspace_schedules?.additional_email_options) { this.adminEmails = this.adminEmails.concat(this.advancedSettings.workspace_schedules?.additional_email_options); } + this.defaultMemoFields = AdvancedSettingsModel.getMemoOptions(configuration, AppName.INTACCT); this.initializeAdvancedSettingsFormWithData(!!expenseFilter.count); this.initializeSkipExportForm(); this.isLoading = false; diff --git a/src/app/integrations/qbd-direct/qbd-direct-main/qbd-direct-dashboard/qbd-direct-dashboard.component.ts b/src/app/integrations/qbd-direct/qbd-direct-main/qbd-direct-dashboard/qbd-direct-dashboard.component.ts index 4847e4e1c..109b27b3b 100644 --- a/src/app/integrations/qbd-direct/qbd-direct-main/qbd-direct-dashboard/qbd-direct-dashboard.component.ts +++ b/src/app/integrations/qbd-direct/qbd-direct-main/qbd-direct-dashboard/qbd-direct-dashboard.component.ts @@ -9,6 +9,7 @@ import { DestinationFieldMap, DashboardModel } from 'src/app/core/models/db/dash import { AccountingGroupedErrors, AccountingGroupedErrorStat, Error, ErrorResponse } from 'src/app/core/models/db/error.model'; import { AppName, AccountingErrorType, QbdDirectTaskLogType, ReimbursableImportState, CCCImportState, AppUrl, TaskLogState } from 'src/app/core/models/enum/enum.model'; import { QbdDirectTaskResponse, QbdDirectTaskLog } from 'src/app/core/models/qbd-direct/db/qbd-direct-task-log.model'; +import { QbdDirectImportSettingModel } from 'src/app/core/models/qbd-direct/qbd-direct-configuration/qbd-direct-import-settings.model'; import { AccountingExportService } from 'src/app/core/services/common/accounting-export.service'; import { DashboardService } from 'src/app/core/services/common/dashboard.service'; import { WorkspaceService } from 'src/app/core/services/common/workspace.service'; @@ -151,7 +152,7 @@ export class QbdDirectDashboardComponent implements OnInit { this.importCodeFields = responses[5].import_settings?.import_code_fields; - this.chartOfAccounts = responses[5].import_settings.chart_of_accounts; + this.chartOfAccounts = responses[5].import_settings.import_account_as_category ? responses[5].import_settings.chart_of_accounts : QbdDirectImportSettingModel.getChartOfAccountTypesList(); const queuedTasks: QbdDirectTaskLog[] = responses[2].results.filter((task: QbdDirectTaskLog) => this.exportLogProcessingStates.includes(task.status)); this.failedExpenseGroupCount = responses[2].results.filter((task: QbdDirectTaskLog) => task.status === TaskLogState.ERROR || task.status === TaskLogState.FATAL).length; diff --git a/src/app/integrations/qbd-direct/qbd-direct-main/qbd-direct-mapping/qbd-direct-base-mapping/qbd-direct-base-mapping.component.ts b/src/app/integrations/qbd-direct/qbd-direct-main/qbd-direct-mapping/qbd-direct-base-mapping/qbd-direct-base-mapping.component.ts index 6e7266fc9..abfd042d8 100644 --- a/src/app/integrations/qbd-direct/qbd-direct-main/qbd-direct-mapping/qbd-direct-base-mapping/qbd-direct-base-mapping.component.ts +++ b/src/app/integrations/qbd-direct/qbd-direct-main/qbd-direct-mapping/qbd-direct-base-mapping/qbd-direct-base-mapping.component.ts @@ -8,6 +8,7 @@ import { MappingSetting } from 'src/app/core/models/db/mapping-setting.model'; import { FyleField, AppName, AccountingField, QBDReimbursableExpensesObject, QBDCorporateCreditCardExpensesObject, NameInJournalEntry } from 'src/app/core/models/enum/enum.model'; import { QbdDirectDestinationAttribute } from 'src/app/core/models/qbd-direct/db/qbd-direct-destination-attribuite.model'; import { QbdDirectExportSettingGet } from 'src/app/core/models/qbd-direct/qbd-direct-configuration/qbd-direct-export-settings.model'; +import { QbdDirectImportSettingModel } from 'src/app/core/models/qbd-direct/qbd-direct-configuration/qbd-direct-import-settings.model'; import { IntegrationsToastService } from 'src/app/core/services/common/integrations-toast.service'; import { MappingService } from 'src/app/core/services/common/mapping.service'; import { WorkspaceService } from 'src/app/core/services/common/workspace.service'; @@ -106,7 +107,7 @@ export class QbdDirectBaseMappingComponent implements OnInit { this.cccExpenseObject = responses[0].credit_card_expense_export_type; this.employeeFieldMapping = (responses[0].employee_field_mapping as unknown as FyleField); this.nameInJE = responses[0].name_in_journal_entry; - this.chartOfAccounts = responses[1].import_settings.chart_of_accounts; + this.chartOfAccounts = responses[1].import_settings.import_account_as_category ? responses[1].import_settings.chart_of_accounts : QbdDirectImportSettingModel.getChartOfAccountTypesList(); this.destinationField = this.getDestinationField(responses[0], responses[2].results); diff --git a/src/app/integrations/qbd-direct/qbd-direct-onboarding/qbd-direct-onboarding-connector/qbd-direct-onboarding-connector.component.ts b/src/app/integrations/qbd-direct/qbd-direct-onboarding/qbd-direct-onboarding-connector/qbd-direct-onboarding-connector.component.ts index ed2533c6b..a1bb46e03 100644 --- a/src/app/integrations/qbd-direct/qbd-direct-onboarding/qbd-direct-onboarding-connector/qbd-direct-onboarding-connector.component.ts +++ b/src/app/integrations/qbd-direct/qbd-direct-onboarding/qbd-direct-onboarding-connector/qbd-direct-onboarding-connector.component.ts @@ -83,18 +83,18 @@ export class QbdDirectOnboardingConnectorComponent implements OnInit { ) { } triggerDownload(filePath: string) { - const normalizedPath = filePath.replace(/\\\\/g, "\\"); - const filePathRegex = /^(\/?|\.?\/?|[a-zA-Z]:\\)([a-zA-Z0-9_-]+[\\/])*[a-zA-Z0-9 _-]+\.qbw$/; - this.isCompanyPathInvalid = filePathRegex.test(normalizedPath); - if (this.isCompanyPathInvalid) { + if (filePath) { this.isDownloadfileLoading = true; - this.qbdDirectConnectorService.postQbdDirectConntion({file_location: normalizedPath}).subscribe((connectionResponse: QbdConnectorGet) => { - this.password = connectionResponse.password; - this.xmlFileContent = connectionResponse.qwc; - this.triggerManualDownload(); - this.showDownloadLink = true; + this.isCompanyPathInvalid = false; + this.qbdDirectConnectorService.postQbdDirectConntion({file_location: filePath}).subscribe((connectionResponse: QbdConnectorGet) => { + this.password = connectionResponse.password; + this.xmlFileContent = connectionResponse.qwc; + this.triggerManualDownload(); + this.showDownloadLink = true; }); this.isDownloadfileLoading = false; + } else { + this.isCompanyPathInvalid = true; } } diff --git a/src/app/integrations/qbd-direct/qbd-direct-shared/qbd-direct-advanced-settings/qbd-direct-advanced-settings.component.html b/src/app/integrations/qbd-direct/qbd-direct-shared/qbd-direct-advanced-settings/qbd-direct-advanced-settings.component.html index 2240fea34..9d5c3cfd6 100644 --- a/src/app/integrations/qbd-direct/qbd-direct-shared/qbd-direct-advanced-settings/qbd-direct-advanced-settings.component.html +++ b/src/app/integrations/qbd-direct/qbd-direct-shared/qbd-direct-advanced-settings/qbd-direct-advanced-settings.component.html @@ -8,6 +8,7 @@ [contentText]="brandingContent.contentText" [showSyncButton]="isOnboarding" [appName]="appName.QBD_DIRECT" + [redirectLink]="redirectLink" (refreshDimension)="refreshDimensions()"> @@ -88,6 +89,12 @@ [placeholder]="'Select top memo type'" [formControllerName]="'topMemoStructure'"> +
{{brandingContent.previewDescriptionFieldLabel}}
+