Skip to content

feat: branding based conditions to feature flag #1179

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/app/auth/login/login.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { StorageService } from 'src/app/core/services/common/storage.service';
import { NetsuiteAuthService } from 'src/app/core/services/netsuite/netsuite-core/netsuite-auth.service';
import { XeroAuthService } from 'src/app/core/services/xero/xero-core/xero-auth.service';
import { exposeAppConfig } from 'src/app/branding/expose-app-config';
import { brandingConfig } from 'src/app/branding/branding-config';
import { brandingConfig, brandingFeatureConfig } from 'src/app/branding/branding-config';
import { QbdDirectAuthService } from 'src/app/core/services/qbd-direct/qbd-direct-core/qbd-direct-auth.service';

@Component({
Expand Down Expand Up @@ -51,7 +51,7 @@ export class LoginComponent implements OnInit {

private redirect(redirectUri: string | undefined, code:string): void {
if (redirectUri) {
brandingConfig.brandId === 'co' ? this.router.navigate([redirectUri], { queryParams: { code: code } }) : this.router.navigate([redirectUri]);
brandingFeatureConfig.loginRedirectUri ? this.router.navigate([redirectUri], { queryParams: { code: code } }) : this.router.navigate([redirectUri]);
} else {
this.router.navigate(['/integrations']);
}
Expand Down
17 changes: 14 additions & 3 deletions src/app/branding/c1-branding-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,22 @@ export const c1FeatureConfig: FeatureConfiguration[string] = {
isBackgroundColorAllowed: true,
isAsterikAllowed: false,
allowIntacctHelperDoc: false,
loginRedirectUri: true,
featureFlags: {
cloneSettings: false,
mapEmployees: false,
showOptionalTextInsteadOfAsterisk: true,
useCustomIcon: true,
displayAppLogoInDashboard: true,
contentVersion: 'v2',
exportSettings: {
reimbursableExpenses: false,
nameInJournalEntry: false,
useMerchantInJournalLine: false,
splitExpenseGrouping: false
splitExpenseGrouping: false,
isEmployeeMappingFixed: true,
transformContentToSentenceCase: true,
isReimbursableExpensesAllowed: false
},
importSettings: {
tax: false,
Expand All @@ -31,7 +39,9 @@ export const c1FeatureConfig: FeatureConfiguration[string] = {
importProjects: true,
allowCustomSegment: false,
dependentField: true,
allowImportCode: false
allowImportCode: false,
importSettingsV1: false,
disableCustomerSourceField: true
},
advancedSettings: {
autoCreateVendors: false,
Expand All @@ -42,7 +52,8 @@ export const c1FeatureConfig: FeatureConfiguration[string] = {
skipExport: false,
autoCreateContacts: false,
useEmployeeAttributes: true,
autoCreateMerchants: true
autoCreateMerchants: true,
excludeCardNumberAndEmployeeNameInMemo: true
},
exportLog: {
expenseType: false
Expand Down
17 changes: 14 additions & 3 deletions src/app/branding/fyle-branding-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,22 @@ export const fyleFeatureConfig: FeatureConfiguration[string] = {
isBackgroundColorAllowed: false,
isAsterikAllowed: true,
allowIntacctHelperDoc: true,
loginRedirectUri: false,
featureFlags: {
cloneSettings: true,
mapEmployees: true,
showOptionalTextInsteadOfAsterisk: false,
useCustomIcon: false,
displayAppLogoInDashboard: false,
contentVersion: 'v1',
exportSettings: {
reimbursableExpenses: true,
nameInJournalEntry: true,
useMerchantInJournalLine: true,
splitExpenseGrouping: true
splitExpenseGrouping: true,
isEmployeeMappingFixed: false,
transformContentToSentenceCase: false,
isReimbursableExpensesAllowed: true
},
importSettings: {
tax: true,
Expand All @@ -31,7 +39,9 @@ export const fyleFeatureConfig: FeatureConfiguration[string] = {
importProjects: true,
allowCustomSegment: true,
dependentField: true,
allowImportCode: true
allowImportCode: true,
importSettingsV1: true,
disableCustomerSourceField: false
},
advancedSettings: {
autoCreateVendors: true,
Expand All @@ -42,7 +52,8 @@ export const fyleFeatureConfig: FeatureConfiguration[string] = {
skipExport: true,
autoCreateContacts: true,
useEmployeeAttributes: true,
autoCreateMerchants: true
autoCreateMerchants: true,
excludeCardNumberAndEmployeeNameInMemo: false
},
exportLog: {
expenseType: true
Expand Down
11 changes: 11 additions & 0 deletions src/app/core/models/branding/feature-configuration.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,22 @@ export type FeatureConfiguration = {
isBackgroundColorAllowed: boolean;
isAsterikAllowed: boolean;
allowIntacctHelperDoc: boolean;
loginRedirectUri: boolean;
featureFlags: {
showOptionalTextInsteadOfAsterisk: boolean;
cloneSettings: boolean;
mapEmployees: boolean;
useCustomIcon: boolean;
displayAppLogoInDashboard: boolean;
contentVersion: string;
exportSettings: {
isReimbursableExpensesAllowed: boolean;
reimbursableExpenses: boolean;
nameInJournalEntry: boolean;
useMerchantInJournalLine: boolean;
splitExpenseGrouping: boolean;
isEmployeeMappingFixed: boolean;
transformContentToSentenceCase: boolean;
},
importSettings: {
tax: boolean;
Expand All @@ -25,6 +33,8 @@ export type FeatureConfiguration = {
allowCustomSegment: boolean;
dependentField: boolean;
allowImportCode: boolean;
importSettingsV1: boolean;
disableCustomerSourceField: boolean;
},
advancedSettings: {
autoCreateVendors: boolean;
Expand All @@ -36,6 +46,7 @@ export type FeatureConfiguration = {
autoCreateContacts: boolean;
useEmployeeAttributes: boolean;
autoCreateMerchants: boolean;
excludeCardNumberAndEmployeeNameInMemo: boolean;
},
exportLog: {
expenseType: boolean;
Expand Down
10 changes: 5 additions & 5 deletions src/app/core/models/common/advanced-settings.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ExportSettingGet } from "../intacct/intacct-configuration/export-settin
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";
import { brandingConfig } from 'src/app/branding/branding-config';
import { brandingConfig, brandingContent, brandingFeatureConfig } from 'src/app/branding/branding-config';
export type EmailOption = {
email: string;
name: string;
Expand Down Expand Up @@ -88,12 +88,12 @@ export class AdvancedSettingsModel {
cccExportType = exportSettings.workspace_general_settings?.corporate_credit_card_expenses_object ?? undefined;
}

if (brandingConfig.brandId === 'co') {
if (brandingFeatureConfig.featureFlags.advancedSettings.excludeCardNumberAndEmployeeNameInMemo) {
return defaultOptions.filter(option => option !== 'card_number' && option !== 'employee_name');
}
if (cccExportType && ['netsuite', 'quickbooks online', 'sage intacct'].includes(appName.toLowerCase()) && brandingConfig.brandId === 'fyle') {
return defaultOptions;
}
if (cccExportType && ['netsuite', 'quickbooks online', 'sage intacct'].includes(appName.toLowerCase()) && !brandingFeatureConfig.featureFlags.advancedSettings.excludeCardNumberAndEmployeeNameInMemo) {
return defaultOptions;
}
return defaultOptions.filter(option => option !== 'card_number');

}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FormGroup } from "@angular/forms";
import { DefaultDestinationAttribute } from "../../db/destination-attribute.model";
import { FyleField } from "../../enum/enum.model";
import { brandingConfig } from "src/app/branding/branding-config";
import { brandingConfig, brandingFeatureConfig } from "src/app/branding/branding-config";
import { ImportSettingsCustomFieldRow } from "../../common/import-settings.model";

const emptyDestinationAttribute = { id: null, name: null };
Expand Down Expand Up @@ -88,7 +88,7 @@ export class ImportSettings {

let isCategoryImportEnabled = false;

if (brandingConfig.brandId === 'fyle') {
if (brandingFeatureConfig.featureFlags.importSettings.importSettingsV1) {
isCategoryImportEnabled = importSettingsForm.get('importCategories')?.value ? importSettingsForm.get('importCategories')?.value : false;
} else {
isCategoryImportEnabled = filteredExpenseFieldArray.filter((field: MappingSetting) => field.source_field === 'CATEGORY' && field.import_to_fyle).length > 0 ? true : false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { DefaultDestinationAttribute } from "../../db/destination-attribute.mode
import { AppName, NetsuiteDefaultLevelOptions, NetsuitePaymentSyncDirection, PaymentSyncDirection } from "../../enum/enum.model";
import { AdvancedSettingValidatorRule, AdvancedSettingsModel } from "../../common/advanced-settings.model";
import { HelperUtility } from "../../common/helper.model";
import { brandingConfig } from "src/app/branding/branding-config";
import { brandingConfig, brandingFeatureConfig } from "src/app/branding/branding-config";
import { environment } from "src/environments/environment";
import { NetSuiteExportSettingGet } from "./netsuite-export-setting.model";

Expand Down Expand Up @@ -75,7 +75,7 @@ export class NetsuiteAdvancedSettingModel extends HelperUtility {
const defaultOptions = this.getDefaultMemoOptions();
const cccExportType = exportSettings.configuration.corporate_credit_card_expenses_object;

if (brandingConfig.brandId === 'co') {
if (brandingFeatureConfig.featureFlags.advancedSettings.excludeCardNumberAndEmployeeNameInMemo) {
return defaultOptions.filter(option => !['card_number', 'employee_name'].includes(option));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,25 +89,9 @@ export class NetSuiteExportSettingModel extends ExportSettingModel {
];
}

static getCoCreditCardExportTypes(): SelectFormOption[] {
return [
{
label: 'Bill',
value: NetSuiteCorporateCreditCardExpensesObject.BILL
},
{
label: 'Credit Card Charge',
value: NetSuiteCorporateCreditCardExpensesObject.CREDIT_CARD_CHARGE
},
{
label: 'Journal Entry',
value: NetSuiteCorporateCreditCardExpensesObject.JOURNAL_ENTRY
}
];
}

static getCreditCardExportTypes(): SelectFormOption[] {
return [

const exportType = [
{
label: 'Bill',
value: NetSuiteCorporateCreditCardExpensesObject.BILL
Expand All @@ -121,10 +105,14 @@ export class NetSuiteExportSettingModel extends ExportSettingModel {
value: NetSuiteCorporateCreditCardExpensesObject.JOURNAL_ENTRY
},
{
label: 'Expense Report',
value: NetSuiteCorporateCreditCardExpensesObject.EXPENSE_REPORT
label: 'Expense Report',
value: NetSuiteCorporateCreditCardExpensesObject.EXPENSE_REPORT
}
];
if (!brandingFeatureConfig.featureFlags.exportSettings.isReimbursableExpensesAllowed) {
return exportType.filter((item) => item.value !== NetSuiteCorporateCreditCardExpensesObject.EXPENSE_REPORT);
}
return exportType;
}

static getCCCExpenseStateOptions(): SelectFormOption[] {
Expand Down Expand Up @@ -264,7 +252,7 @@ export class NetSuiteExportSettingModel extends ExportSettingModel {
}

static getEmployeeFieldMapping(employeeFieldMapping: string): string {
return brandingConfig.brandId === 'co' ? EmployeeFieldMapping.VENDOR : employeeFieldMapping;
return brandingFeatureConfig.featureFlags.exportSettings.isEmployeeMappingFixed ? EmployeeFieldMapping.VENDOR : employeeFieldMapping;
}

static mapAPIResponseToFormGroup(exportSettings: NetSuiteExportSettingGet | null): FormGroup {
Expand Down Expand Up @@ -295,7 +283,7 @@ export class NetSuiteExportSettingModel extends ExportSettingModel {
const emptyDestinationAttribute: DefaultDestinationAttribute = {id: null, name: null};
const nameInJournalEntry = exportSettingsForm.get('nameInJournalEntry')?.value ? exportSettingsForm.get('nameInJournalEntry')?.value : NameInJournalEntry.EMPLOYEE;

if (brandingConfig.brandId === 'co') {
if (brandingFeatureConfig.featureFlags.exportSettings.isEmployeeMappingFixed) {
exportSettingsForm.controls.creditCardExpense.patchValue(true);
exportSettingsForm.controls.employeeFieldMapping.patchValue(FyleField.VENDOR);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ImportSettingGeneralMapping } from "../../intacct/intacct-configuration
import { XeroWorkspaceGeneralSetting } from "../db/xero-workspace-general-setting.model";
import { ImportSettingMappingRow, ImportSettingsModel } from "../../common/import-settings.model";
import { IntegrationField } from "../../db/mapping.model";
import { brandingConfig } from "src/app/branding/branding-config";
import { brandingConfig, brandingFeatureConfig } from "src/app/branding/branding-config";
import { ExportSettingModel } from "../../common/export-settings.model";


Expand Down Expand Up @@ -65,7 +65,7 @@ export class XeroImportSettingModel extends ImportSettingsModel {

static mapAPIResponseToFormGroup(importSettings: XeroImportSettingGet | null, xeroFields: IntegrationField[], isCustomerPresent:boolean, destinationAttribute: DestinationAttribute[]): FormGroup {
let additionalOption: any[] = [];
if (brandingConfig.brandId === 'co' && isCustomerPresent) {
if (brandingFeatureConfig.featureFlags.importSettings.disableCustomerSourceField && isCustomerPresent) {
const additionalMappingSetting = {
source_field: 'DISABLED_XERO_SOURCE_FIELD',
destination_field: XeroFyleField.CUSTOMER,
Expand Down
4 changes: 2 additions & 2 deletions src/app/core/services/common/helper.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { ExportModuleRule, ExportSettingValidatorRule } from '../../models/sage3
import { SnakeCaseToSpaceCasePipe } from 'src/app/shared/pipes/snake-case-to-space-case.pipe';
import { SkipExportValidatorRule, skipExportValidator } from '../../models/common/advanced-settings.model';
import { StorageService } from './storage.service';
import { brandingConfig } from 'src/app/branding/branding-config';
import { brandingConfig, brandingFeatureConfig } from 'src/app/branding/branding-config';
import { SentenceCasePipe } from 'src/app/shared/pipes/sentence-case.pipe';
import { TitleCasePipe } from '@angular/common';
import { DefaultDestinationAttribute, DestinationAttribute } from '../../models/db/destination-attribute.model';
Expand Down Expand Up @@ -260,7 +260,7 @@ export class HelperService {

sentenseCaseConversion(content: string) {
content = new SnakeCaseToSpaceCasePipe().transform(content);
return brandingConfig.brandId === 'co' ? new SentenceCasePipe().transform(content) : content;
return brandingFeatureConfig.featureFlags.exportSettings.transformContentToSentenceCase ? new SentenceCasePipe().transform(content) : content;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { IntacctConfigurationComponent } from './intacct-configuration.component
import { IntacctExportSettingsComponent } from '../../intacct-shared/intacct-export-settings/intacct-export-settings.component';
import { IntacctImportSettingsComponent } from '../../intacct-shared/intacct-import-settings/intacct-import-settings.component';
import { IntacctAdvancedSettingsComponent } from '../../intacct-shared/intacct-advanced-settings/intacct-advanced-settings.component';
import { brandingConfig } from 'src/app/branding/branding-config';
import { brandingConfig, brandingFeatureConfig } from 'src/app/branding/branding-config';
import { IntacctC1ImportSettingsComponent } from '../../intacct-shared/intacct-c1-import-settings/intacct-c1-import-settings.component';
import { IntacctConnectorComponent } from 'src/app/shared/components/si/core/intacct-connector/intacct-connector.component';

Expand All @@ -23,7 +23,7 @@ const routes: Routes = [
},
{
path: 'import_settings',
component: brandingConfig.brandId === 'fyle' ? IntacctImportSettingsComponent : IntacctC1ImportSettingsComponent
component: !brandingFeatureConfig.featureFlags.importSettings.importSettingsV1 ? IntacctImportSettingsComponent : IntacctC1ImportSettingsComponent
},
{
path: 'advanced_settings',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { brandingConfig, brandingFeatureConfig } from 'src/app/branding/branding
import { mockMappingSettingsResponse, mockMappingSettingsWithCustomFieldResponse } from '../../intacct.fixture';
import { MappingSettingResponse } from 'src/app/core/models/intacct/db/mapping-setting.model';
import { SharedModule } from 'src/app/shared/shared.module';
import { c1FeatureConfig } from 'src/app/branding/c1-branding-config';
import { fyleFeatureConfig } from 'src/app/branding/fyle-branding-config';

describe('IntacctMappingComponent', () => {
let component: IntacctMappingComponent;
Expand Down Expand Up @@ -70,8 +72,12 @@ describe('IntacctMappingComponent', () => {
it('should handle different branding configurations', () => {
mappingServiceSpy.getMappingSettings.and.returnValue(of(mockMappingSettingsWithCustomFieldResponse as MappingSettingResponse));
brandingConfig.brandId = 'co';
brandingFeatureConfig.featureFlags.exportSettings.transformContentToSentenceCase = c1FeatureConfig.featureFlags.exportSettings.transformContentToSentenceCase;

fixture.detectChanges();

expect(component.mappingPages[3].label).toBe('Sample custom field');

brandingFeatureConfig.featureFlags.exportSettings.transformContentToSentenceCase = fyleFeatureConfig.featureFlags.exportSettings.transformContentToSentenceCase;
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export class IntacctMappingComponent implements OnInit {
if (item.source_field !== FyleField.EMPLOYEE && item.source_field !== FyleField.CATEGORY) {
const mappingPage = new SnakeCaseToSpaceCasePipe().transform(item.source_field);
this.mappingPages.push({
label: brandingConfig.brandId === 'co' ? new SentenceCasePipe().transform(mappingPage) : new TitleCasePipe().transform(mappingPage),
label: brandingFeatureConfig.featureFlags.exportSettings.transformContentToSentenceCase ? new SentenceCasePipe().transform(mappingPage) : new TitleCasePipe().transform(mappingPage),
routerLink: `/integrations/intacct/main/mapping/${encodeURIComponent(item.source_field.toLowerCase())}`
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
</div>
<form [formGroup]="exportSettingsForm">
<div class="tw-p-24-px" [ngClass]="{'tw-pt-0': !brandingFeatureConfig.featureFlags.exportSettings.reimbursableExpenses}">
<div *ngIf="brandingConfig.brandId === 'fyle'" class="tw-mb-16-px">
<div *ngIf="brandingFeatureConfig.featureFlags.exportSettings.isReimbursableExpensesAllowed" class="tw-mb-16-px">
<div *ngIf="brandingFeatureConfig.featureFlags.exportSettings.reimbursableExpenses" class="tw-rounded-lg tw-border-separator tw-border tw-bg-configuration-bg">
<app-configuration-toggle-field
[form]="exportSettingsForm"
Expand Down
Loading