Skip to content

Commit d7391cf

Browse files
kfleminCopilot
andauthored
Add BB Salesforce Configs (#58)
* complete Salesforce settings migration and fix bugs * salesforce bb configs --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
1 parent b749ed9 commit d7391cf

6 files changed

Lines changed: 401 additions & 100 deletions

File tree

src/@seed/api/organization/organization.types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export type BriefOrganization = {
2323
user_role: UserRole;
2424
display_decimal_places: number;
2525
salesforce_enabled: boolean;
26+
bb_salesforce_enabled: boolean;
2627
access_level_names: string[];
2728
audit_template_conditional_import: boolean;
2829
property_display_field: string;
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import type { HttpErrorResponse } from '@angular/common/http'
2+
import { HttpClient } from '@angular/common/http'
3+
import { inject, Injectable } from '@angular/core'
4+
import type { Observable } from 'rxjs'
5+
import { catchError, map, ReplaySubject } from 'rxjs'
6+
import { ErrorService } from '@seed/services'
7+
import { SnackBarService } from 'app/core/snack-bar/snack-bar.service'
8+
import { UserService } from '../user'
9+
import type {
10+
BbSalesforceConfig,
11+
BbSalesforceConfigResponse,
12+
BbSalesforceConfigsResponse,
13+
BbSalesforceLoginUrlResponse,
14+
BbSalesforceLogoutResponse,
15+
BbSalesforceTokenResponse,
16+
BbSalesforceVerifyTokenResponse,
17+
} from './salesforce.types'
18+
19+
@Injectable({ providedIn: 'root' })
20+
export class BbSalesforceService {
21+
private _httpClient = inject(HttpClient)
22+
private _errorService = inject(ErrorService)
23+
private _snackBar = inject(SnackBarService)
24+
private _userService = inject(UserService)
25+
26+
private _config = new ReplaySubject<BbSalesforceConfig>(1)
27+
28+
config$ = this._config.asObservable()
29+
30+
constructor() {
31+
this._userService.currentOrganizationId$.subscribe((organizationId) => {
32+
this.getConfig(organizationId).subscribe()
33+
})
34+
}
35+
36+
getConfig(organizationId: number): Observable<BbSalesforceConfigsResponse> {
37+
const url = `/api/v3/bb_salesforce/configs/?organization_id=${organizationId}`
38+
return this._httpClient.get<BbSalesforceConfigsResponse>(url).pipe(
39+
map((response) => {
40+
if (response.bb_salesforce_configs.length === 0) {
41+
this._config.next({} as BbSalesforceConfig)
42+
} else {
43+
this._config.next(response.bb_salesforce_configs[0])
44+
}
45+
return response
46+
}),
47+
catchError((error: HttpErrorResponse) => {
48+
return this._errorService.handleError(error, 'Error fetching BB Salesforce config')
49+
}),
50+
)
51+
}
52+
53+
create(organizationId: number, config: Partial<BbSalesforceConfig>): Observable<BbSalesforceConfig> {
54+
const url = `/api/v3/bb_salesforce/configs/?organization_id=${organizationId}`
55+
return this._httpClient.post<BbSalesforceConfigResponse>(url, { ...config }).pipe(
56+
map((response) => {
57+
this._config.next(response.bb_salesforce_config)
58+
return response.bb_salesforce_config
59+
}),
60+
catchError((error: HttpErrorResponse) => {
61+
return this._errorService.handleError(error, 'Error creating BB Salesforce config')
62+
}),
63+
)
64+
}
65+
66+
update(organizationId: number, config: BbSalesforceConfig): Observable<BbSalesforceConfig> {
67+
const url = `/api/v3/bb_salesforce/configs/update_config/?organization_id=${organizationId}`
68+
return this._httpClient.put<BbSalesforceConfigResponse>(url, { ...config }).pipe(
69+
map((response) => {
70+
this._snackBar.success('BB Salesforce configuration updated')
71+
this._config.next(response.bb_salesforce_config)
72+
return response.bb_salesforce_config
73+
}),
74+
catchError((error: HttpErrorResponse) => {
75+
return this._errorService.handleError(error, 'Error updating BB Salesforce config')
76+
}),
77+
)
78+
}
79+
80+
delete(organizationId: number, configId: number): Observable<object> {
81+
const url = `/api/v3/bb_salesforce/configs/${configId}/?organization_id=${organizationId}`
82+
return this._httpClient.delete(url).pipe(
83+
map(() => {
84+
this._config.next({} as BbSalesforceConfig)
85+
return {}
86+
}),
87+
catchError((error: HttpErrorResponse) => {
88+
return this._errorService.handleError(error, 'Error deleting BB Salesforce config')
89+
}),
90+
)
91+
}
92+
93+
getLoginUrl(organizationId: number): Observable<BbSalesforceLoginUrlResponse> {
94+
const url = `/api/v3/bb_salesforce/login_url/?organization_id=${organizationId}`
95+
return this._httpClient.get<BbSalesforceLoginUrlResponse>(url).pipe(
96+
catchError((error: HttpErrorResponse) => {
97+
return this._errorService.handleError(error, 'Cannot login to Salesforce. Double check the Salesforce login URL.')
98+
}),
99+
)
100+
}
101+
102+
getToken(code: string, organizationId: number): Observable<BbSalesforceTokenResponse> {
103+
const url = `/api/v3/bb_salesforce/get_token/?code=${code}&organization_id=${organizationId}`
104+
return this._httpClient.get<BbSalesforceTokenResponse>(url).pipe(
105+
catchError((error: HttpErrorResponse) => {
106+
return this._errorService.handleError(error, 'Error exchanging Salesforce authorization code')
107+
}),
108+
)
109+
}
110+
111+
logout(organizationId: number): Observable<BbSalesforceLogoutResponse> {
112+
const url = `/api/v3/bb_salesforce/logout/?organization_id=${organizationId}`
113+
return this._httpClient.get<BbSalesforceLogoutResponse>(url).pipe(
114+
map((response) => {
115+
this._snackBar.success('Successfully logged out of Salesforce')
116+
return response
117+
}),
118+
catchError((error: HttpErrorResponse) => {
119+
return this._errorService.handleError(error, 'Error logging out of Salesforce')
120+
}),
121+
)
122+
}
123+
124+
verifyToken(organizationId: number): Observable<BbSalesforceVerifyTokenResponse> {
125+
const url = `/api/v3/bb_salesforce/verify_token/?organization_id=${organizationId}`
126+
return this._httpClient.get<BbSalesforceVerifyTokenResponse>(url).pipe(
127+
catchError((error: HttpErrorResponse) => {
128+
return this._errorService.handleError(error, 'Error verifying Salesforce token')
129+
}),
130+
)
131+
}
132+
}

src/@seed/api/salesforce/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
export * from './bb-salesforce.service'
12
export * from './salesforce.service'
23
export * from './salesforce.types'

src/@seed/api/salesforce/salesforce.types.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,43 @@ export type SalesforceMapping = {
4949
salesforce_fieldname: string;
5050
}
5151

52+
export type BbSalesforceConfig = {
53+
id: number;
54+
organization_id: number;
55+
salesforce_url: string;
56+
client_id: string;
57+
client_secret: string;
58+
}
59+
60+
export type BbSalesforceConfigResponse = {
61+
status: string;
62+
bb_salesforce_config: BbSalesforceConfig;
63+
}
64+
65+
export type BbSalesforceConfigsResponse = {
66+
status: string;
67+
bb_salesforce_configs: BbSalesforceConfig[];
68+
}
69+
70+
export type BbSalesforceLoginUrlResponse = {
71+
status: string;
72+
url?: string;
73+
response?: string;
74+
}
75+
76+
export type BbSalesforceTokenResponse = {
77+
status: string;
78+
response?: string;
79+
}
80+
81+
export type BbSalesforceVerifyTokenResponse = {
82+
valid: boolean;
83+
}
84+
85+
export type BbSalesforceLogoutResponse = {
86+
status: string;
87+
}
88+
5289
export type SalesforceMappingDeleteResponse = {
5390
status: string;
5491
message: string;

0 commit comments

Comments
 (0)