Skip to content

Commit

Permalink
xero master (#574)
Browse files Browse the repository at this point in the history
xero master
  • Loading branch information
DhaaraniCIT authored Mar 7, 2024
1 parent 0118af2 commit 17b5635
Show file tree
Hide file tree
Showing 111 changed files with 1,929 additions and 14 deletions.
5 changes: 5 additions & 0 deletions run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ do
sed -i $SED_EXTRA_ARGS "s?{{SAGE300_API_URL}}?${SAGE300_API_URL}?g" $f;
sed -i $SED_EXTRA_ARGS "s?{{BUSINESS_CENTRAL_API_URL}}?${BUSINESS_CENTRAL_API_URL}?g" $f;
sed -i $SED_EXTRA_ARGS "s?{{QBO_API_URL}}?${QBO_API_URL}?g" $f;
sed -i $SED_EXTRA_ARGS "s?{{XERO_API_URL}}?${XERO_API_URL}?g" $f;
sed -i $SED_EXTRA_ARGS "s?{{NETSUITE_API_URL}}?${NETSUITE_API_URL}?g" $f;
sed -i $SED_EXTRA_ARGS "s?{{FYLE_APP_URL}}?${FYLE_APP_URL}?g" $f;
sed -i $SED_EXTRA_ARGS "s?{{CALLBACK_URI}}?${CALLBACK_URI}?g" $f;
Expand Down Expand Up @@ -40,6 +41,10 @@ do
sed -i $SED_EXTRA_ARGS "s?{{REFINER_INTACCT_EXPORT_DONE_SURVEY_ID}}?${REFINER_INTACCT_EXPORT_DONE_SURVEY_ID}?g" $f;
sed -i $SED_EXTRA_ARGS "s?{{BUSINESS_CENTRAL_OAUTH_REDIRECT_URI}}?${BUSINESS_CENTRAL_OAUTH_REDIRECT_URI}?g" $f;
sed -i $SED_EXTRA_ARGS "s?{{BUSINESS_CENTRAL_OAUTH_CLIENT_ID}}?${BUSINESS_CENTRAL_OAUTH_CLIENT_ID}?g" $f;
sed -i $SED_EXTRA_ARGS "s?{{XERO_OAUTH_CLIENT_ID}}?${XERO_OAUTH_CLIENT_ID}?g" $f;
sed -i $SED_EXTRA_ARGS "s?{{XERO_SCOPE}}?${XERO_SCOPE}?g" $f;
sed -i $SED_EXTRA_ARGS "s?{{XERO_AUTHORIZE_URI}}?${XERO_AUTHORIZE_URI}?g" $f;
sed -i $SED_EXTRA_ARGS "s?{{XERO_OAUTH_REDIRECT_URI}}?${XERO_OAUTH_REDIRECT_URI}?g" $f;
sed -i $SED_EXTRA_ARGS "s?{{BRAND_NAME}}?${BRAND_NAME}?g" $f;
sed -i $SED_EXTRA_ARGS "s?{{WEBPAGE_TITLE}}?${WEBPAGE_TITLE}?g" $f;
sed -i $SED_EXTRA_ARGS "s?{{BRAND_ID}}?${BRAND_ID}?g" $f;
Expand Down
5 changes: 5 additions & 0 deletions scripts/setup_env.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const environment = {
netsuite_api_url: `${process.env.NETSUITE_API_URL ? process.env.NETSUITE_API_URL : '{{NETSUITE_API_URL}}'}`,
business_central_api_url: `${process.env.BUSINESS_CENTRAL_API_URL ? process.env.BUSINESS_CENTRAL_API_URL : '{{BUSINESS_CENTRAL_API_URL}}'}`,
qbo_api_url: `${process.env.QBO_API_URL ? process.env.QBO_API_URL : '{{QBO_API_URL}}'}`,
xero_api_url: `${process.env.XERO_API_URL ? process.env.XERO_API_URL : '{{XERO_API_URL}}'}`,
netsuite_api_url: `${process.env.NETSUITE_API_URL ? process.env.NETSUITE_API_URL : '{{NETSUITE_API_URL}}'}`,
cluster_domain_api_url: `${process.env.CLUSTER_DOMAIN_API_URL ? process.env.CLUSTER_DOMAIN_API_URL : '{{CLUSTER_DOMAIN_API_URL}}'}`,
fyle_app_url: `${process.env.FYLE_APP_URL ? process.env.FYLE_APP_URL : '{{FYLE_APP_URL}}'}`,
Expand All @@ -31,6 +32,10 @@ const environment = {
qbo_oauth_redirect_uri: `${process.env.QBO_OAUTH_REDIRECT_URI ? process.env.QBO_OAUTH_REDIRECT_URI : '{{QBO_OAUTH_REDIRECT_URI}}'}`,
qbo_authorize_uri: `${process.env.QBO_AUTHORIZE_URI ? process.env.QBO_AUTHORIZE_URI : '{{QBO_AUTHORIZE_URI}}'}`,
qbo_oauth_client_id: `${process.env.QBO_OAUTH_CLIENT_ID ? process.env.QBO_OAUTH_CLIENT_ID : '{{QBO_OAUTH_CLIENT_ID}}'}`,
xero_oauth_client_id: `${process.env.XERO_OAUTH_CLIENT_ID ? process.env.XERO_OAUTH_CLIENT_ID : '{{XERO_OAUTH_CLIENT_ID}}'}`,
xero_scope: `${process.env.XERO_SCOPE ? process.env.XERO_SCOPE : '{{XERO_SCOPE}}'}`,
xero_authorize_uri: `${process.env.XERO_AUTHORIZE_URI ? process.env.XERO_AUTHORIZE_URI : '{{XERO_AUTHORIZE_URI}}'}`,
xero_oauth_redirect_uri: `${process.env.XERO_OAUTH_REDIRECT_URI ? process.env.XERO_OAUTH_REDIRECT_URI : '{{XERO_OAUTH_REDIRECT_URI}}'}`,
refiner_survey: {
intacct: {
onboarding_done_survery_id: `${process.env.REFINER_INTACCT_ONBOARDING_DONE_SURVEY_ID ? process.env.REFINER_INTACCT_ONBOARDING_DONE_SURVEY_ID : '{{REFINER_INTACCT_ONBOARDING_DONE_SURVEY_ID}}'}`,
Expand Down
8 changes: 4 additions & 4 deletions src/app/auth/login/login.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { AppUrl } from 'src/app/core/models/enum/enum.model';
import { ClusterDomainWithToken } from 'src/app/core/models/misc/token.model';
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';

@Component({
selector: 'app-login',
Expand All @@ -33,6 +34,7 @@ export class LoginComponent implements OnInit {
private sage300AuthService: Sage300AuthService,
private siAuthService : SiAuthService,
private netsuiteAuthService: NetsuiteAuthService,
private xeroAuthService: XeroAuthService,
private storageService: StorageService,
private userService: UserService
) { }
Expand Down Expand Up @@ -70,10 +72,6 @@ export class LoginComponent implements OnInit {
this.helperService.setBaseApiURL(AppUrl.BUSINESS_CENTRAL);
this.businessCentralAuthService.loginWithRefreshToken(clusterDomainWithToken.tokens.refresh_token).subscribe();

this.helperService.setBaseApiURL(AppUrl.NETSUITE);
this.netsuiteAuthService.loginWithRefreshToken(clusterDomainWithToken.tokens.refresh_token).subscribe();


// Only local dev needs this, login happens via postMessage for prod/staging through webapp
if (!environment.production) {
this.userService.storeUserProfile(user);
Expand All @@ -83,6 +81,8 @@ export class LoginComponent implements OnInit {
this.siAuthService.loginWithRefreshToken(clusterDomainWithToken.tokens.refresh_token).subscribe();
this.helperService.setBaseApiURL(AppUrl.NETSUITE);
this.netsuiteAuthService.loginWithRefreshToken(clusterDomainWithToken.tokens.refresh_token).subscribe();
this.helperService.setBaseApiURL(AppUrl.XERO);
this.xeroAuthService.loginWithRefreshToken(clusterDomainWithToken.tokens.refresh_token).subscribe();
this.redirect(redirectUri);
} else {
this.redirect(redirectUri);
Expand Down
15 changes: 15 additions & 0 deletions src/app/core/guard/tenant.guard.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { TestBed } from '@angular/core/testing';
import { TenantGuard } from './tenant.guard';

describe('WorkspacesGuard', () => {
let guard: TenantGuard;

beforeEach(() => {
TestBed.configureTestingModule({});
guard = TestBed.inject(TenantGuard);
});

it('should be created', () => {
expect(guard).toBeTruthy();
});
});
49 changes: 49 additions & 0 deletions src/app/core/guard/tenant.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
import { forkJoin, Observable, throwError } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { globalCacheBusterNotifier } from 'ts-cacheable';
import { ToastSeverity, XeroOnboardingState } from '../models/enum/enum.model';
import { XeroConnectorService } from '../services/xero/xero-configuration/xero-connector.service';
import { WorkspaceService } from '../services/common/workspace.service';
import { IntegrationsToastService } from '../services/common/integrations-toast.service';

@Injectable({
providedIn: 'root'
})
export class TenantGuard implements CanActivate {

constructor(
private xeroConnectorService: XeroConnectorService,
private router: Router,
private workspaceService: WorkspaceService,
private toastService: IntegrationsToastService
) { }

canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
const workspaceId = this.workspaceService.getWorkspaceId();

if (!workspaceId) {
return this.router.navigateByUrl(`workspaces`);
}

return forkJoin(
[
this.xeroConnectorService.getTenantMappings()
]
).pipe(
map(response => !!response),
catchError(error => {
if (error.status === 400) {
globalCacheBusterNotifier.next();
this.toastService.displayToastMessage(ToastSeverity.ERROR, 'Oops! You will need to select a tenant to proceed with the onboarding.');
return this.router.navigateByUrl('integrations/xero/onboarding/xero_connector');
}
return throwError(error);
})
);
}

}
16 changes: 16 additions & 0 deletions src/app/core/guard/xero-token.guard.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';

import { XeroTokenGuard } from './xero-token.guard';

describe('XeroTokenGuard', () => {
let guard: XeroTokenGuard;

beforeEach(() => {
TestBed.configureTestingModule({});
guard = TestBed.inject(XeroTokenGuard);
});

it('should be created', () => {
expect(guard).toBeTruthy();
});
});
55 changes: 55 additions & 0 deletions src/app/core/guard/xero-token.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Injectable } from "@angular/core";
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from "@angular/router";
import { XeroConnectorService } from "../services/xero/xero-configuration/xero-connector.service";
import { Observable, forkJoin, map, catchError, throwError } from "rxjs";
import { globalCacheBusterNotifier } from "ts-cacheable";
import { WorkspaceService } from "../services/common/workspace.service";
import { ToastSeverity, XeroOnboardingState } from "../models/enum/enum.model";
import { IntegrationsToastService } from "../services/common/integrations-toast.service";


@Injectable({
providedIn: 'root'
})
export class XeroTokenGuard implements CanActivate {

constructor(
private xeroConnectorService: XeroConnectorService,
private router: Router,
private toastService: IntegrationsToastService,
private workspaceService: WorkspaceService
) { }

canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {

const workspaceId = this.workspaceService.getWorkspaceId();

if (!workspaceId) {
return this.router.navigateByUrl(`workspaces`);
}

return forkJoin(
[
this.xeroConnectorService.getXeroCredentials(workspaceId),
this.xeroConnectorService.getXeroTokenHealth(workspaceId)
]
).pipe(
map(response => !!response),
catchError(error => {
if (error.status === 400) {
globalCacheBusterNotifier.next();
this.toastService.displayToastMessage(ToastSeverity.ERROR, 'Oops! Your Xero connection expired, please connect again');

const onboardingState: XeroOnboardingState = this.workspaceService.getOnboardingState();

return this.router.navigateByUrl('integrations/xero/onboarding/landing');
}

return throwError(error);
})
);
}

}
4 changes: 2 additions & 2 deletions src/app/core/models/db/expense-group-setting.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { CCCExpenseState, ExpenseState, ExportDateType } from "../enum/enum.mode
export type ExpenseGroupSettingPost = {
expense_state: ExpenseState;
ccc_expense_state: CCCExpenseState;
reimbursable_expense_group_fields: string[] | null;
reimbursable_expense_group_fields?: string[] | null;
reimbursable_export_date_type: ExportDateType | null;
corporate_credit_card_expense_group_fields: string[] | null;
corporate_credit_card_expense_group_fields?: string[] | null;
ccc_export_date_type: ExportDateType | null;
};

Expand Down
31 changes: 29 additions & 2 deletions src/app/core/models/enum/enum.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,15 @@ export enum QBOOnboardingState {
CLONE_SETTINGS = 'CLONE_SETTINGS'
}

export enum XeroOnboardingState {
CONNECTION = 'CONNECTION',
EXPORT_SETTINGS = 'EXPORT_SETTINGS',
IMPORT_SETTINGS = 'IMPORT_SETTINGS',
ADVANCED_CONFIGURATION = 'ADVANCED_CONFIGURATION',
COMPLETE = 'COMPLETE',
CLONE_SETTINGS = 'CLONE_SETTINGS'
}

export enum NetsuiteOnboardingState {
CONNECTION = 'CONNECTION',
EXPORT_SETTINGS = 'EXPORT_SETTINGS',
Expand Down Expand Up @@ -211,6 +220,14 @@ export enum QBOCorporateCreditCardExpensesObject {
DEBIT_CARD_EXPENSE = 'DEBIT CARD EXPENSE'
}

export enum XeroReimbursableExpensesObject {
PURCHASE_BILL = 'PURCHASE BILL'
}

export enum XeroCorporateCreditCardExpensesObject {
BANK_TRANSACTION = 'BANK TRANSACTION'
}

export enum NameInJournalEntry {
EMPLOYEE = 'EMPLOYEE',
MERCHANT = 'MERCHANT'
Expand Down Expand Up @@ -334,7 +351,9 @@ export enum QBDAccountingExportsType {

export enum PaymentSyncDirection {
FYLE_TO_INTACCT = 'fyle_to_intacct',
INTACCT_TO_FYLE = 'intacct_to_fyle'
INTACCT_TO_FYLE = 'intacct_to_fyle',
FYLE_TO_XERO = 'fyle_to_xero',
XERO_TO_FYLE = 'xero_to_fyle'
}

export enum QBOPaymentSyncDirection {
Expand Down Expand Up @@ -463,7 +482,8 @@ export enum AppUrl {
BUSINESS_CENTRAL = 'business_central',
INTEGRATION = 'integration',
QBO = 'qbo',
NETSUITE = 'netsuite'
NETSUITE = 'netsuite',
XERO = 'xero'
}

export enum Sage300ExportType {
Expand Down Expand Up @@ -595,6 +615,13 @@ export enum QBOTaskLogType {
FETCHING_EXPENSE = 'FETCHING_EXPENSE'
}

export enum XeroTaskLogType {
CREATING_BILL = 'CREATING_BILL',
CREATING_BANK_TRANSACTION = 'CREATING_BANK_TRANSACTION',
CREATING_PAYMENT = 'CREATING_PAYMENT',
FETCHING_EXPENSE = 'FETCHING_EXPENSE'
}

export enum LoaderType {
DETERMINATE = 'determinate',
INDETERMINATE = 'indeterminate'
Expand Down
1 change: 1 addition & 0 deletions src/app/core/models/integrations/integrations.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,5 @@ export type AppUrlMap = {
[AppUrl.BUSINESS_CENTRAL]: string
[AppUrl.QBO]: string
[AppUrl.NETSUITE]: string
[AppUrl.XERO]: string
}
9 changes: 9 additions & 0 deletions src/app/core/models/xero/db/xero-credential.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export type XeroCredentials = {
id: number;
refresh_token: string;
company_name: string;
country: string;
created_at: Date;
updated_at: Date;
workspace: number;
};
25 changes: 25 additions & 0 deletions src/app/core/models/xero/db/xero-task-log.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { PaginatedResponse } from "../../db/paginated-response.model";
import { TaskLog } from "../../db/task-log.model";
import { XeroTaskLogType } from "../../enum/enum.model";

export type XeroError = {
expense_group_id: number;
short_description: string;
long_description: string;
type: string;
};

export interface XeroTaskLogs extends TaskLog {
bill: number;
cheque: number;
credit_card_purchase: number;
xero_errors: XeroError[];
journal_entry: number;
bill_payment: number;
task_id: string;
type: XeroTaskLogType;
}

export interface XeroTaskResponse extends PaginatedResponse {
results: Task[];
}
15 changes: 15 additions & 0 deletions src/app/core/models/xero/db/xero-tenant-mapping.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* Tslint:disable */
export type TenantMapping = {
id: number;
tenant_name: string;
tenant_id: string;
connection_id: string;
created_at: Date;
updated_at: Date;
workspace: number;
};

export type TenantMappingPost = {
tenant_id: string;
tenant_name: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export type XeroWorkspaceGeneralSetting = {
id?: number;
reimbursable_expenses_object: string;
corporate_credit_card_expenses_object: string;
import_projects?: boolean;
import_categories: boolean;
charts_of_accounts: string[];
change_accounting_period: boolean;
sync_fyle_to_xero_payments: boolean;
sync_xero_to_fyle_payments: boolean;
map_merchant_to_contact: boolean;
auto_map_employees: string;
auto_create_destination_entity: boolean;
is_simplify_report_closure_enabled: boolean;
skip_cards_mapping?: boolean;
import_tax_codes: boolean;
import_customers: boolean;
import_suppliers_as_merchants: boolean;
created_at?: Date;
updated_at?: Date;
workspace?: number;
};
14 changes: 14 additions & 0 deletions src/app/core/models/xero/db/xero-workspace.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Workspace } from "../../db/workspaces.model";
import { XeroOnboardingState } from "../../enum/enum.model";

export interface XeroWorkspace extends Workspace {
onboarding_state: XeroOnboardingState;
fyle_currency: string;
xero_currency: string;
fyle_org_id: string;
xero_short_code: string;
last_synced_at?: Date;
ccc_last_synced_at: Date;
source_synced_at: Date;
destination_synced_at: Date;
}
Loading

0 comments on commit 17b5635

Please sign in to comment.