Skip to content

Commit 8c2a8c5

Browse files
authored
Merge pull request Expensify#44159 from shubham1206agra/netsuite-export
[#Wave-Control: Add NetSuite]: Settings Configuration in NewDot: Export
2 parents 51c505b + 480878c commit 8c2a8c5

File tree

47 files changed

+2333
-91
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+2333
-91
lines changed

src/CONST.ts

+125-4
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ const CONST = {
364364
NETSUITE_ON_NEW_EXPENSIFY: 'netsuiteOnNewExpensify',
365365
REPORT_FIELDS_FEATURE: 'reportFieldsFeature',
366366
WORKSPACE_FEEDS: 'workspaceFeeds',
367+
NETSUITE_USA_TAX: 'netsuiteUsaTax',
367368
},
368369
BUTTON_STATES: {
369370
DEFAULT: 'default',
@@ -1337,10 +1338,6 @@ const CONST = {
13371338
},
13381339
},
13391340

1340-
NETSUITE_CONFIG: {
1341-
SUBSIDIARY: 'subsidiary',
1342-
},
1343-
13441341
QUICKBOOKS_REIMBURSABLE_ACCOUNT_TYPE: {
13451342
VENDOR_BILL: 'bill',
13461343
CHECK: 'check',
@@ -1353,6 +1350,130 @@ const CONST = {
13531350
REPORT_SUBMITTED: 'REPORT_SUBMITTED',
13541351
},
13551352

1353+
NETSUITE_CONFIG: {
1354+
SUBSIDIARY: 'subsidiary',
1355+
EXPORTER: 'exporter',
1356+
EXPORT_DATE: 'exportDate',
1357+
REIMBURSABLE_EXPENSES_EXPORT_DESTINATION: 'reimbursableExpensesExportDestination',
1358+
NON_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION: 'nonreimbursableExpensesExportDestination',
1359+
DEFAULT_VENDOR: 'defaultVendor',
1360+
REIMBURSABLE_PAYABLE_ACCOUNT: 'reimbursablePayableAccount',
1361+
PAYABLE_ACCT: 'payableAcct',
1362+
JOURNAL_POSTING_PREFERENCE: 'journalPostingPreference',
1363+
RECEIVABLE_ACCOUNT: 'receivableAccount',
1364+
INVOICE_ITEM_PREFERENCE: 'invoiceItemPreference',
1365+
INVOICE_ITEM: 'invoiceItem',
1366+
TAX_POSTING_ACCOUNT: 'taxPostingAccount',
1367+
PROVINCIAL_TAX_POSTING_ACCOUNT: 'provincialTaxPostingAccount',
1368+
ALLOW_FOREIGN_CURRENCY: 'allowForeignCurrency',
1369+
EXPORT_TO_NEXT_OPEN_PERIOD: 'exportToNextOpenPeriod',
1370+
},
1371+
1372+
NETSUITE_EXPORT_DATE: {
1373+
LAST_EXPENSE: 'LAST_EXPENSE',
1374+
EXPORTED: 'EXPORTED',
1375+
SUBMITTED: 'SUBMITTED',
1376+
},
1377+
1378+
NETSUITE_EXPORT_DESTINATION: {
1379+
EXPENSE_REPORT: 'EXPENSE_REPORT',
1380+
VENDOR_BILL: 'VENDOR_BILL',
1381+
JOURNAL_ENTRY: 'JOURNAL_ENTRY',
1382+
},
1383+
1384+
NETSUITE_INVOICE_ITEM_PREFERENCE: {
1385+
CREATE: 'create',
1386+
SELECT: 'select',
1387+
},
1388+
1389+
NETSUITE_JOURNAL_POSTING_PREFERENCE: {
1390+
JOURNALS_POSTING_INDIVIDUAL_LINE: 'JOURNALS_POSTING_INDIVIDUAL_LINE',
1391+
JOURNALS_POSTING_TOTAL_LINE: 'JOURNALS_POSTING_TOTAL_LINE',
1392+
},
1393+
1394+
NETSUITE_EXPENSE_TYPE: {
1395+
REIMBURSABLE: 'reimbursable',
1396+
NON_REIMBURSABLE: 'nonreimbursable',
1397+
},
1398+
1399+
/**
1400+
* Countries where tax setting is permitted (Strings are in the format of Netsuite's Country type/enum)
1401+
*
1402+
* Should mirror the list on the OldDot.
1403+
*/
1404+
NETSUITE_TAX_COUNTRIES: [
1405+
'_canada',
1406+
'_unitedKingdomGB',
1407+
'_unitedKingdom',
1408+
'_australia',
1409+
'_southAfrica',
1410+
'_india',
1411+
'_france',
1412+
'_netherlands',
1413+
'_germany',
1414+
'_singapore',
1415+
'_spain',
1416+
'_ireland',
1417+
'_denmark',
1418+
'_brazil',
1419+
'_japan',
1420+
'_philippines',
1421+
'_china',
1422+
'_argentina',
1423+
'_newZealand',
1424+
'_switzerland',
1425+
'_sweden',
1426+
'_portugal',
1427+
'_mexico',
1428+
'_israel',
1429+
'_thailand',
1430+
'_czechRepublic',
1431+
'_egypt',
1432+
'_ghana',
1433+
'_indonesia',
1434+
'_iranIslamicRepublicOf',
1435+
'_jordan',
1436+
'_kenya',
1437+
'_kuwait',
1438+
'_lebanon',
1439+
'_malaysia',
1440+
'_morocco',
1441+
'_myanmar',
1442+
'_nigeria',
1443+
'_pakistan',
1444+
'_saudiArabia',
1445+
'_sriLanka',
1446+
'_unitedArabEmirates',
1447+
'_vietnam',
1448+
'_austria',
1449+
'_bulgaria',
1450+
'_greece',
1451+
'_cyprus',
1452+
'_norway',
1453+
'_romania',
1454+
'_poland',
1455+
'_hongKong',
1456+
'_luxembourg',
1457+
'_lithuania',
1458+
'_malta',
1459+
'_finland',
1460+
'_koreaRepublicOf',
1461+
'_italy',
1462+
'_georgia',
1463+
'_hungary',
1464+
'_latvia',
1465+
'_estonia',
1466+
'_slovenia',
1467+
'_serbia',
1468+
'_croatiaHrvatska',
1469+
'_belgium',
1470+
'_turkey',
1471+
'_taiwan',
1472+
'_azerbaijan',
1473+
'_slovakRepublic',
1474+
'_costaRica',
1475+
] as string[],
1476+
13561477
QUICKBOOKS_EXPORT_DATE: {
13571478
LAST_EXPENSE: 'LAST_EXPENSE',
13581479
REPORT_EXPORTED: 'REPORT_EXPORTED',

src/ROUTES.ts

+60-3
Original file line numberDiff line numberDiff line change
@@ -932,13 +932,70 @@ const ROUTES = {
932932
route: 'settings/workspaces/:policyID/accounting/quickbooks-online/import/taxes',
933933
getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/quickbooks-online/import/taxes` as const,
934934
},
935+
RESTRICTED_ACTION: {
936+
route: 'restricted-action/workspace/:policyID',
937+
getRoute: (policyID: string) => `restricted-action/workspace/${policyID}` as const,
938+
},
935939
POLICY_ACCOUNTING_NETSUITE_SUBSIDIARY_SELECTOR: {
936940
route: 'settings/workspaces/:policyID/accounting/net-suite/subsidiary-selector',
937941
getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/net-suite/subsidiary-selector` as const,
938942
},
939-
RESTRICTED_ACTION: {
940-
route: 'restricted-action/workspace/:policyID',
941-
getRoute: (policyID: string) => `restricted-action/workspace/${policyID}` as const,
943+
POLICY_ACCOUNTING_NETSUITE_EXPORT: {
944+
route: 'settings/workspaces/:policyID/connections/netsuite/export/',
945+
getRoute: (policyID: string) => `settings/workspaces/${policyID}/connections/netsuite/export/` as const,
946+
},
947+
POLICY_ACCOUNTING_NETSUITE_PREFERRED_EXPORTER_SELECT: {
948+
route: 'settings/workspaces/:policyID/connections/netsuite/export/preferred-exporter/select',
949+
getRoute: (policyID: string) => `settings/workspaces/${policyID}/connections/netsuite/export/preferred-exporter/select` as const,
950+
},
951+
POLICY_ACCOUNTING_NETSUITE_DATE_SELECT: {
952+
route: 'settings/workspaces/:policyID/connections/netsuite/export/date/select',
953+
getRoute: (policyID: string) => `settings/workspaces/${policyID}/connections/netsuite/export/date/select` as const,
954+
},
955+
POLICY_ACCOUNTING_NETSUITE_EXPORT_EXPENSES: {
956+
route: 'settings/workspaces/:policyID/connections/netsuite/export/expenses/:expenseType',
957+
getRoute: (policyID: string, expenseType: ValueOf<typeof CONST.NETSUITE_EXPENSE_TYPE>) =>
958+
`settings/workspaces/${policyID}/connections/netsuite/export/expenses/${expenseType}` as const,
959+
},
960+
POLICY_ACCOUNTING_NETSUITE_EXPORT_EXPENSES_DESTINATION_SELECT: {
961+
route: 'settings/workspaces/:policyID/connections/netsuite/export/expenses/:expenseType/destination/select',
962+
getRoute: (policyID: string, expenseType: ValueOf<typeof CONST.NETSUITE_EXPENSE_TYPE>) =>
963+
`settings/workspaces/${policyID}/connections/netsuite/export/expenses/${expenseType}/destination/select` as const,
964+
},
965+
POLICY_ACCOUNTING_NETSUITE_EXPORT_EXPENSES_VENDOR_SELECT: {
966+
route: 'settings/workspaces/:policyID/connections/netsuite/export/expenses/:expenseType/vendor/select',
967+
getRoute: (policyID: string, expenseType: ValueOf<typeof CONST.NETSUITE_EXPENSE_TYPE>) =>
968+
`settings/workspaces/${policyID}/connections/netsuite/export/expenses/${expenseType}/vendor/select` as const,
969+
},
970+
POLICY_ACCOUNTING_NETSUITE_EXPORT_EXPENSES_PAYABLE_ACCOUNT_SELECT: {
971+
route: 'settings/workspaces/:policyID/connections/netsuite/export/expenses/:expenseType/payable-account/select',
972+
getRoute: (policyID: string, expenseType: ValueOf<typeof CONST.NETSUITE_EXPENSE_TYPE>) =>
973+
`settings/workspaces/${policyID}/connections/netsuite/export/expenses/${expenseType}/payable-account/select` as const,
974+
},
975+
POLICY_ACCOUNTING_NETSUITE_EXPORT_EXPENSES_JOURNAL_POSTING_PREFERENCE_SELECT: {
976+
route: 'settings/workspaces/:policyID/connections/netsuite/export/expenses/:expenseType/journal-posting-preference/select',
977+
getRoute: (policyID: string, expenseType: ValueOf<typeof CONST.NETSUITE_EXPENSE_TYPE>) =>
978+
`settings/workspaces/${policyID}/connections/netsuite/export/expenses/${expenseType}/journal-posting-preference/select` as const,
979+
},
980+
POLICY_ACCOUNTING_NETSUITE_RECEIVABLE_ACCOUNT_SELECT: {
981+
route: 'settings/workspaces/:policyID/connections/netsuite/export/receivable-account/select',
982+
getRoute: (policyID: string) => `settings/workspaces/${policyID}/connections/netsuite/export/receivable-account/select` as const,
983+
},
984+
POLICY_ACCOUNTING_NETSUITE_INVOICE_ITEM_PREFERENCE_SELECT: {
985+
route: 'settings/workspaces/:policyID/connections/netsuite/export/invoice-item-preference/select',
986+
getRoute: (policyID: string) => `settings/workspaces/${policyID}/connections/netsuite/export/invoice-item-preference/select` as const,
987+
},
988+
POLICY_ACCOUNTING_NETSUITE_INVOICE_ITEM_SELECT: {
989+
route: 'settings/workspaces/:policyID/connections/netsuite/export/invoice-item-preference/invoice-item/select',
990+
getRoute: (policyID: string) => `settings/workspaces/${policyID}/connections/netsuite/export/invoice-item-preference/invoice-item/select` as const,
991+
},
992+
POLICY_ACCOUNTING_NETSUITE_TAX_POSTING_ACCOUNT_SELECT: {
993+
route: 'settings/workspaces/:policyID/connections/netsuite/export/tax-posting-account/select',
994+
getRoute: (policyID: string) => `settings/workspaces/${policyID}/connections/netsuite/export/tax-posting-account/select` as const,
995+
},
996+
POLICY_ACCOUNTING_NETSUITE_PROVINCIAL_TAX_POSTING_ACCOUNT_SELECT: {
997+
route: 'settings/workspaces/:policyID/connections/netsuite/export/provincial-tax-posting-account/select',
998+
getRoute: (policyID: string) => `settings/workspaces/${policyID}/connections/netsuite/export/provincial-tax-posting-account/select` as const,
942999
},
9431000
POLICY_ACCOUNTING_SAGE_INTACCT_PREREQUISITES: {
9441001
route: 'settings/workspaces/:policyID/accounting/sage-intacct/prerequisites',

src/SCREENS.ts

+13
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,19 @@ const SCREENS = {
273273
XERO_BILL_PAYMENT_ACCOUNT_SELECTOR: 'Policy_Accounting_Xero_Bill_Payment_Account_Selector',
274274
XERO_EXPORT_BANK_ACCOUNT_SELECT: 'Policy_Accounting_Xero_Export_Bank_Account_Select',
275275
NETSUITE_SUBSIDIARY_SELECTOR: 'Policy_Accounting_Net_Suite_Subsidiary_Selector',
276+
NETSUITE_EXPORT: 'Policy_Accounting_NetSuite_Export',
277+
NETSUITE_PREFERRED_EXPORTER_SELECT: 'Policy_Accounting_NetSuite_Preferred_Exporter_Select',
278+
NETSUITE_DATE_SELECT: 'Policy_Accounting_NetSuite_Date_Select',
279+
NETSUITE_EXPORT_EXPENSES: 'Policy_Accounting_NetSuite_Export_Expenses',
280+
NETSUITE_EXPORT_EXPENSES_DESTINATION_SELECT: 'Policy_Accounting_NetSuite_Export_Expenses_Destination_Select',
281+
NETSUITE_EXPORT_EXPENSES_VENDOR_SELECT: 'Policy_Accounting_NetSuite_Export_Expenses_Vendor_Select',
282+
NETSUITE_EXPORT_EXPENSES_PAYABLE_ACCOUNT_SELECT: 'Policy_Accounting_NetSuite_Export_Expenses_Payable_Account_Select',
283+
NETSUITE_EXPORT_EXPENSES_JOURNAL_POSTING_PREFERENCE_SELECT: 'Policy_Accounting_NetSuite_Export_Expenses_Journal_Posting_Preference_Select',
284+
NETSUITE_RECEIVABLE_ACCOUNT_SELECT: 'Policy_Accounting_NetSuite_Receivable_Account_Select',
285+
NETSUITE_INVOICE_ITEM_PREFERENCE_SELECT: 'Policy_Accounting_NetSuite_Invoice_Item_Preference_Select',
286+
NETSUITE_INVOICE_ITEM_SELECT: 'Policy_Accounting_NetSuite_Invoice_Item_Select',
287+
NETSUITE_TAX_POSTING_ACCOUNT_SELECT: 'Policy_Accounting_NetSuite_Tax_Posting_Account_Select',
288+
NETSUITE_PROVINCIAL_TAX_POSTING_ACCOUNT_SELECT: 'Policy_Accounting_NetSuite_Provincial_Tax_Posting_Account_Select',
276289
SAGE_INTACCT_PREREQUISITES: 'Policy_Accounting_Sage_Intacct_Prerequisites',
277290
ENTER_SAGE_INTACCT_CREDENTIALS: 'Policy_Enter_Sage_Intacct_Credentials',
278291
EXISTING_SAGE_INTACCT_CONNECTIONS: 'Policy_Existing_Sage_Intacct_Connections',

src/components/ConnectionLayout.tsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import * as PolicyUtils from '@libs/PolicyUtils';
99
import type {AccessVariant} from '@pages/workspace/AccessOrNotFoundWrapper';
1010
import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
1111
import type {TranslationPaths} from '@src/languages/types';
12+
import type {Route} from '@src/ROUTES';
1213
import type {ConnectionName, PolicyFeatureName} from '@src/types/onyx/Policy';
1314
import HeaderWithBackButton from './HeaderWithBackButton';
1415
import ScreenWrapper from './ScreenWrapper';
@@ -19,6 +20,9 @@ type ConnectionLayoutProps = {
1920
/** Used to set the testID for tests */
2021
displayName: string;
2122

23+
/* The route on back button press */
24+
onBackButtonPressRoute?: Route;
25+
2226
/** Header title to be translated for the connection component */
2327
headerTitle?: TranslationPaths;
2428

@@ -77,6 +81,7 @@ function ConnectionLayoutContent({title, titleStyle, children, titleAlreadyTrans
7781

7882
function ConnectionLayout({
7983
displayName,
84+
onBackButtonPressRoute,
8085
headerTitle,
8186
children,
8287
title,
@@ -125,7 +130,7 @@ function ConnectionLayout({
125130
<HeaderWithBackButton
126131
title={headerTitleAlreadyTranslated ?? (headerTitle ? translate(headerTitle) : '')}
127132
subtitle={headerSubtitle}
128-
onBackButtonPress={() => Navigation.goBack()}
133+
onBackButtonPress={() => Navigation.goBack(onBackButtonPressRoute)}
129134
/>
130135
{shouldUseScrollView ? (
131136
<ScrollView contentContainerStyle={contentContainerStyle}>{renderSelectionContent}</ScrollView>

src/components/HTMLEngineProvider/BaseHTMLEngineProvider.tsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ function BaseHTMLEngineProvider({textSelectable = false, children, enableExperim
4242
mixedUAStyles: {...styles.colorMuted, ...styles.mb0},
4343
contentModel: HTMLContentModel.block,
4444
}),
45+
'muted-text-label': HTMLElementModel.fromCustomModel({
46+
tagName: 'muted-text-label',
47+
mixedUAStyles: {...styles.mutedNormalTextLabel, ...styles.mb0},
48+
contentModel: HTMLContentModel.block,
49+
}),
4550
comment: HTMLElementModel.fromCustomModel({
4651
tagName: 'comment',
4752
mixedUAStyles: {whiteSpace: 'pre'},
@@ -83,7 +88,7 @@ function BaseHTMLEngineProvider({textSelectable = false, children, enableExperim
8388
contentModel: HTMLContentModel.block,
8489
}),
8590
}),
86-
[styles.formError, styles.mb0, styles.colorMuted, styles.textLabelSupporting, styles.lh16, styles.textSupporting, styles.textLineThrough, styles.mt4],
91+
[styles.formError, styles.mb0, styles.colorMuted, styles.textLabelSupporting, styles.lh16, styles.textSupporting, styles.textLineThrough, styles.mt4, styles.mutedNormalTextLabel],
8792
);
8893
/* eslint-enable @typescript-eslint/naming-convention */
8994

src/components/MenuItem.tsx

+30-1
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,9 @@ type MenuItemBaseProps = {
254254
/** Whether should render title as HTML or as Text */
255255
shouldParseTitle?: boolean;
256256

257+
/** Whether should render helper text as HTML or as Text */
258+
shouldParseHelperText?: boolean;
259+
257260
/** Should check anonymous user in onPress function */
258261
shouldCheckActionAllowedOnPress?: boolean;
259262

@@ -372,6 +375,7 @@ function MenuItem(
372375
isAnonymousAction = false,
373376
shouldBlockSelection = false,
374377
shouldParseTitle = false,
378+
shouldParseHelperText = false,
375379
shouldCheckActionAllowedOnPress = true,
376380
onSecondaryInteraction,
377381
titleWithTooltips,
@@ -429,6 +433,14 @@ function MenuItem(
429433
return parser.replace(title, {shouldEscapeText});
430434
}, [title, shouldParseTitle, shouldEscapeText]);
431435

436+
const helperHtml = useMemo(() => {
437+
if (!helperText || !shouldParseHelperText) {
438+
return '';
439+
}
440+
const parser = new ExpensiMark();
441+
return parser.replace(helperText, {shouldEscapeText});
442+
}, [helperText, shouldParseHelperText, shouldEscapeText]);
443+
432444
const processedTitle = useMemo(() => {
433445
let titleToWrap = '';
434446
if (shouldRenderAsHTML) {
@@ -442,6 +454,16 @@ function MenuItem(
442454
return titleToWrap ? `<comment>${titleToWrap}</comment>` : '';
443455
}, [title, shouldRenderAsHTML, shouldParseTitle, html]);
444456

457+
const processedHelperText = useMemo(() => {
458+
let textToWrap = '';
459+
460+
if (shouldParseHelperText) {
461+
textToWrap = helperHtml;
462+
}
463+
464+
return textToWrap ? `<comment><muted-text-label>${textToWrap}</muted-text-label></comment>` : '';
465+
}, [shouldParseHelperText, helperHtml]);
466+
445467
const hasPressableRightComponent = iconRight || (shouldShowRightComponent && rightComponent);
446468

447469
const renderTitleContent = () => {
@@ -767,7 +789,14 @@ function MenuItem(
767789
</PressableWithSecondaryInteraction>
768790
)}
769791
</Hoverable>
770-
{!!helperText && <Text style={[styles.mutedNormalTextLabel, styles.ph5, styles.pb5, helperTextStyle]}>{helperText}</Text>}
792+
{!!helperText &&
793+
(shouldParseHelperText ? (
794+
<View style={[styles.flexRow, styles.renderHTML, styles.ph5, styles.pb5]}>
795+
<RenderHTML html={processedHelperText} />
796+
</View>
797+
) : (
798+
<Text style={[styles.mutedNormalTextLabel, styles.ph5, styles.pb5, helperTextStyle]}>{helperText}</Text>
799+
))}
771800
</View>
772801
</EducationalTooltip>
773802
</View>

src/components/SelectionScreen.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ type SelectionScreenProps = {
3131
/** Content to display if the list is empty */
3232
listEmptyContent?: React.JSX.Element | null;
3333

34+
/** Custom content to display in the footer of list component. */
35+
listFooterContent?: React.JSX.Element | null;
36+
3437
/** Sections for the section list */
3538
sections: Array<SectionListDataType<SelectorType>>;
3639

@@ -67,6 +70,7 @@ function SelectionScreen({
6770
title,
6871
headerContent,
6972
listEmptyContent,
73+
listFooterContent,
7074
sections,
7175
listItem,
7276
initiallyFocusedOptionKey,
@@ -107,6 +111,7 @@ function SelectionScreen({
107111
shouldShowTooltips={false}
108112
initiallyFocusedOptionKey={initiallyFocusedOptionKey}
109113
listEmptyContent={listEmptyContent}
114+
listFooterContent={listFooterContent}
110115
/>
111116
</ScreenWrapper>
112117
</AccessOrNotFoundWrapper>

0 commit comments

Comments
 (0)